diff options
Diffstat (limited to 'src/libs/advanceddockingsystem/dockmanager.cpp')
-rw-r--r-- | src/libs/advanceddockingsystem/dockmanager.cpp | 270 |
1 files changed, 192 insertions, 78 deletions
diff --git a/src/libs/advanceddockingsystem/dockmanager.cpp b/src/libs/advanceddockingsystem/dockmanager.cpp index 051fa68a40..76a62fce92 100644 --- a/src/libs/advanceddockingsystem/dockmanager.cpp +++ b/src/libs/advanceddockingsystem/dockmanager.cpp @@ -36,7 +36,9 @@ #include "dockmanager.h" #include "ads_globals.h" +#include "dockareatitlebar.h" #include "dockareawidget.h" +#include "dockfocuscontroller.h" #include "dockingstatereader.h" #include "dockoverlay.h" #include "dockwidget.h" @@ -72,6 +74,15 @@ static Q_LOGGING_CATEGORY(adsLog, "qtc.qmldesigner.advanceddockingsystem", QtWar namespace ADS { + /** + * Internal file version in case the structure changes internally + */ + enum eStateFileVersion { + InitialVersion = 0, //!< InitialVersion + Version1 = 1, //!< Version1 + CurrentVersion = Version1 //!< CurrentVersion + }; + static DockManager::ConfigFlags g_staticConfigFlags = DockManager::DefaultNonOpaqueConfig; /** @@ -88,6 +99,7 @@ namespace ADS QMap<QString, DockWidget *> m_dockWidgetsMap; bool m_restoringState = false; QVector<FloatingDockContainer *> m_uninitializedFloatingWidgets; + DockFocusController *m_focusController = nullptr; QString m_workspaceName; bool m_workspaceListDirty = true; @@ -98,7 +110,7 @@ namespace ADS bool m_autorestoreLastWorkspace; // This option is set in the Workspace Manager! QSettings *m_settings = nullptr; QString m_workspacePresetsPath; - bool m_modeChangeState; + bool m_modeChangeState = false; /** * Private data constructor @@ -106,17 +118,12 @@ namespace ADS DockManagerPrivate(DockManager *parent); /** - * Checks if the given data stream is a valid docking system state - * file. - */ - bool checkFormat(const QByteArray &state, int version); - - /** - * Restores the state + * Restores the state. If testing is set to true it will check if + * the given data stream is a valid docking system state file. */ bool restoreStateFromXml(const QByteArray &state, int version, - bool testing = internal::restore); + bool testing = false); /** * Restore state @@ -164,21 +171,15 @@ namespace ADS } else { qCInfo(adsLog) << "d->m_containers[i]->restoreState "; auto container = m_containers[index]; - if (container->isFloating()) { + if (container->isFloating()) result = container->floatingWidget()->restoreState(stream, testing); - } else { + else result = container->restoreState(stream, testing); - } } return result; } - bool DockManagerPrivate::checkFormat(const QByteArray &state, int version) - { - return restoreStateFromXml(state, version, internal::restoreTesting); - } - bool DockManagerPrivate::restoreStateFromXml(const QByteArray &state, int version, bool testing) { Q_UNUSED(version) // TODO version is not needed, why is it in here in the first place? @@ -200,6 +201,17 @@ namespace ADS return false; stateReader.setFileVersion(v); + + qCInfo(adsLog) << stateReader.attributes().value("userVersion"); + // Older files do not support UserVersion but we still want to load them so + // we first test if the attribute exists + if (!stateReader.attributes().value("userVersion").isEmpty()) + { + v = stateReader.attributes().value("userVersion").toInt(&ok); + if (!ok || v != version) + return false; + } + bool result = true; #ifdef ADS_DEBUG_PRINT int dockContainers = stateReader.attributes().value("containers").toInt(); @@ -258,9 +270,8 @@ namespace ADS DockAreaWidget *dockArea = dockContainer->dockArea(i); QString dockWidgetName = dockArea->property("currentDockWidget").toString(); DockWidget *dockWidget = nullptr; - if (!dockWidgetName.isEmpty()) { + if (!dockWidgetName.isEmpty()) dockWidget = q->findDockWidget(dockWidgetName); - } if (!dockWidget || dockWidget->isClosed()) { int index = dockArea->indexOfFirstOpenDockWidget(); @@ -286,9 +297,8 @@ namespace ADS } else { for (int i = 0; i < dockContainer->dockAreaCount(); ++i) { auto dockArea = dockContainer->dockArea(i); - for (auto dockWidget : dockArea->dockWidgets()) { + for (auto dockWidget : dockArea->dockWidgets()) dockWidget->emitTopLevelChanged(false); - } } } } @@ -297,7 +307,8 @@ namespace ADS bool DockManagerPrivate::restoreState(const QByteArray &state, int version) { QByteArray currentState = state.startsWith("<?xml") ? state : qUncompress(state); - if (!checkFormat(currentState, version)) { + // Check the format of the given data stream + if (!restoreStateFromXml(currentState, version, true)) { qCInfo(adsLog) << "checkFormat: Error checking format!!!"; return false; } @@ -335,6 +346,9 @@ namespace ADS d->m_dockAreaOverlay = new DockOverlay(this, DockOverlay::ModeDockAreaOverlay); d->m_containerOverlay = new DockOverlay(this, DockOverlay::ModeContainerOverlay); d->m_containers.append(this); + + if (DockManager::configFlags().testFlag(DockManager::FocusHighlighting)) + d->m_focusController = new DockFocusController(this); } DockManager::~DockManager() @@ -407,13 +421,12 @@ namespace ADS DockAreaWidget *DockManager::addDockWidgetTab(DockWidgetArea area, DockWidget *dockWidget) { DockAreaWidget *areaWidget = lastAddedDockAreaWidget(area); - if (areaWidget) { + if (areaWidget) return addDockWidget(ADS::CenterDockWidgetArea, dockWidget, areaWidget); - } else if (!openedDockAreas().isEmpty()) { + else if (!openedDockAreas().isEmpty()) return addDockWidget(area, dockWidget, openedDockAreas().last()); - } else { + else return addDockWidget(area, dockWidget, nullptr); - } } DockAreaWidget *DockManager::addDockWidgetTabToArea(DockWidget *dockWidget, @@ -432,11 +445,11 @@ namespace ADS dockWidget->setDockManager(this); FloatingDockContainer *floatingWidget = new FloatingDockContainer(dockWidget); floatingWidget->resize(dockWidget->size()); - if (isVisible()) { + if (isVisible()) floatingWidget->show(); - } else { + else d->m_uninitializedFloatingWidgets.append(floatingWidget); - } + return floatingWidget; } @@ -459,9 +472,8 @@ namespace ADS void DockManager::removeDockContainer(DockContainerWidget *dockContainer) { - if (this != dockContainer) { + if (this != dockContainer) d->m_containers.removeAll(dockContainer); - } } DockOverlay *DockManager::containerOverlay() const { return d->m_containerOverlay; } @@ -488,7 +500,8 @@ namespace ADS stream.setAutoFormatting(configFlags.testFlag(XmlAutoFormattingEnabled)); stream.writeStartDocument(); stream.writeStartElement("QtAdvancedDockingSystem"); - stream.writeAttribute("version", QString::number(version)); + stream.writeAttribute("version", QString::number(CurrentVersion)); + stream.writeAttribute("userVersion", QString::number(version)); stream.writeAttribute("containers", QString::number(d->m_containers.count())); for (auto container : d->m_containers) container->saveState(stream); @@ -521,10 +534,10 @@ namespace ADS emit restoringState(); bool result = d->restoreState(state, version); d->m_restoringState = false; - emit stateRestored(); if (!isHidden) show(); + emit stateRestored(); return result; } @@ -583,15 +596,14 @@ namespace ADS emit aboutToSaveWorkspace(); bool result = write(activeWorkspace(), saveState(), parentWidget()); - if (result) { + if (result) d->m_workspaceDateTimes.insert(activeWorkspace(), QDateTime::currentDateTime()); - } else { + else QMessageBox::warning(parentWidget(), tr("Cannot Save Workspace"), tr("Could not save workspace to file %1") - .arg(workspaceNameToFileName(d->m_workspaceName) + .arg(workspaceNameToFilePath(d->m_workspaceName) .toUserOutput())); - } return result; } @@ -613,6 +625,8 @@ namespace ADS const QString m_dirName = QLatin1String("workspaces"); const QString m_fileExt = QLatin1String(".wrk"); // TODO + QString DockManager::workspaceFileExtension() const { return m_fileExt; } + QStringList DockManager::workspaces() { if (d->m_workspaces.isEmpty() || d->m_workspaceListDirty) { @@ -622,14 +636,13 @@ namespace ADS QDir workspaceDir(QFileInfo(d->m_settings->fileName()).path() + QLatin1Char('/') + m_dirName); QFileInfoList workspaceFiles - = workspaceDir.entryInfoList(QStringList() << QLatin1String("*.wrk"), + = workspaceDir.entryInfoList(QStringList() << QLatin1Char('*') + m_fileExt, QDir::NoFilter, QDir::Time); for (const QFileInfo &fileInfo : workspaceFiles) { - QString filename = fileInfo.completeBaseName(); - filename.replace("_", " "); - d->m_workspaceDateTimes.insert(filename, fileInfo.lastModified()); - tmp.insert(filename); + QString workspaceName = fileNameToWorkspaceName(fileInfo.completeBaseName()); + d->m_workspaceDateTimes.insert(workspaceName, fileInfo.lastModified()); + tmp.insert(workspaceName); } d->m_workspaceListDirty = false; @@ -643,14 +656,11 @@ namespace ADS if (d->m_workspacePresets.isEmpty()) { QDir workspacePresetsDir(d->m_workspacePresetsPath); QFileInfoList workspacePresetsFiles - = workspacePresetsDir.entryInfoList(QStringList() << QLatin1String("*.wrk"), + = workspacePresetsDir.entryInfoList(QStringList() << QLatin1Char('*') + m_fileExt, QDir::NoFilter, QDir::Time); - for (const QFileInfo &fileInfo : workspacePresetsFiles) { - QString filename = fileInfo.completeBaseName(); - filename.replace("_", " "); - d->m_workspacePresets.insert(filename); - } + for (const QFileInfo &fileInfo : workspacePresetsFiles) + d->m_workspacePresets.insert(fileNameToWorkspaceName(fileInfo.completeBaseName())); } return d->m_workspacePresets; } @@ -660,13 +670,27 @@ namespace ADS return d->m_workspaceDateTimes.value(workspace); } - Utils::FilePath DockManager::workspaceNameToFileName(const QString &workspaceName) const + Utils::FilePath DockManager::workspaceNameToFilePath(const QString &workspaceName) const { QTC_ASSERT(d->m_settings, return {}); - QString workspaceNameCopy = workspaceName; return Utils::FilePath::fromString( QFileInfo(d->m_settings->fileName()).path() + QLatin1Char('/') + m_dirName - + QLatin1Char('/') + workspaceNameCopy.replace(" ", "_") + QLatin1String(".wrk")); + + QLatin1Char('/') + workspaceNameToFileName(workspaceName)); + } + + QString DockManager::fileNameToWorkspaceName(const QString &fileName) const + { + QString copy = QFileInfo(fileName).baseName(); + copy.replace("_", " "); + return copy; + } + + QString DockManager::workspaceNameToFileName(const QString &workspaceName) const + { + QString copy = workspaceName; + copy.replace(" ", "_"); + copy.append(m_fileExt); + return copy; } /** @@ -686,7 +710,7 @@ namespace ADS QMessageBox::warning(parentWidget(), tr("Cannot Save Workspace"), tr("Could not save workspace to file %1") - .arg(workspaceNameToFileName(d->m_workspaceName) + .arg(workspaceNameToFilePath(d->m_workspaceName) .toUserOutput())); } @@ -695,9 +719,9 @@ namespace ADS bool DockManager::openWorkspace(const QString &workspace) { - // Do nothing if we have that workspace already loaded, exception if the - // workspace is the default virgin workspace we still want to be able to - // load the default workspace. + // Do nothing if we have that workspace already loaded, exception if it is + // a preset workspace. In this case we still want to be able to load the + // default workspace to undo potential user changes. if (workspace == d->m_workspaceName && !isWorkspacePreset(workspace)) return true; @@ -775,7 +799,7 @@ namespace ADS return false; // Remove corresponding workspace file - QFile fi(workspaceNameToFileName(workspace).toString()); + QFile fi(workspaceNameToFilePath(workspace).toString()); if (fi.exists()) { if (fi.remove()) { d->m_workspaces.removeOne(workspace); @@ -799,12 +823,12 @@ namespace ADS if (!d->m_workspaces.contains(original)) return false; - QFile fi(workspaceNameToFileName(original).toString()); + QFile fi(workspaceNameToFilePath(original).toString()); // If the file does not exist, we can still clone - if (!fi.exists() || fi.copy(workspaceNameToFileName(clone).toString())) { + if (!fi.exists() || fi.copy(workspaceNameToFilePath(clone).toString())) { d->m_workspaces.insert(1, clone); d->m_workspaceDateTimes - .insert(clone, workspaceNameToFileName(clone).toFileInfo().lastModified()); + .insert(clone, workspaceNameToFilePath(clone).toFileInfo().lastModified()); emit workspaceListChanged(); return true; } @@ -815,8 +839,10 @@ namespace ADS { if (!cloneWorkspace(original, newName)) return false; + if (original == activeWorkspace()) openWorkspace(newName); + return deleteWorkspace(original); } @@ -825,17 +851,14 @@ namespace ADS if (!isWorkspacePreset(workspace)) return false; - Utils::FilePath filename = workspaceNameToFileName(workspace); + Utils::FilePath fileName = workspaceNameToFilePath(workspace); - if (!QFile::remove(filename.toString())) + if (!QFile::remove(fileName.toString())) return false; QDir presetsDir(d->m_workspacePresetsPath); - QString presetName = workspace; - presetName.replace(" ", "_"); - presetName.append(".wrk"); - - bool result = QFile::copy(presetsDir.filePath(presetName), filename.toString()); + bool result = QFile::copy(presetsDir.filePath(workspaceNameToFileName(workspace)), + fileName.toString()); if (result) d->m_workspaceDateTimes.insert(workspace, QDateTime::currentDateTime()); @@ -852,13 +875,89 @@ namespace ADS return d->m_modeChangeState; } + void DockManager::importWorkspace(const QString &workspace) + { + // Extract workspace name + QString workspaceName = fileNameToWorkspaceName(workspace); + + // Check if the workspace is already contained in the list of workspaces. If that is the case + // add a counter to the workspace name. + if (workspaces().contains(workspaceName)) { + int i = 2; + QString copy; + do { + copy = workspaceName + QLatin1String(" (") + QString::number(i) + QLatin1Char(')'); + ++i; + } while (workspaces().contains(copy)); + workspaceName = copy; + } + + QString fileName = workspaceNameToFileName(workspaceName); + QFile file(workspace); + if (!file.exists()) { + qCInfo(adsLog) << QString("File doesn't exist '%1'").arg(workspace); + return; + } + + QDir workspaceDir(QFileInfo(d->m_settings->fileName()).path() + QLatin1Char('/') + m_dirName); + + if (!file.copy(workspaceDir.filePath(fileName))) { + qCInfo(adsLog) << QString("Could not copy '%1' to '%2' error: %3").arg( + workspace, workspaceDir.filePath(fileName), file.errorString()); + } else { + d->m_workspaces.insert(1, workspaceName); + d->m_workspaceDateTimes.insert(workspaceName, + workspaceNameToFilePath(workspaceName).toFileInfo().lastModified()); + d->m_workspaceListDirty = true; + // After importing the workspace, update the workspace list + workspaces(); + emit workspaceListChanged(); + } + } + + void DockManager::exportWorkspace(const QString &target, const QString &workspace) + { + // If we came this far the user decided that in case the target already exists to overwrite it. + // We first need to remove the existing file, otherwise QFile::copy() will fail. + QFileInfo targetFileInfo(target); + + // Remove the file which supposed to be overwritten + if (targetFileInfo.exists()) { + QFile fi(targetFileInfo.absoluteFilePath()); + if (!fi.remove()) { + qCInfo(adsLog) << QString("Couldn't remove '%1'").arg(targetFileInfo.absoluteFilePath()); + return; + } + } + + // Check if the target directory exists + if (!targetFileInfo.absoluteDir().exists()) { + qCInfo(adsLog) << QString("Directory doesn't exist '%1'").arg(targetFileInfo.dir().dirName()); + return; + } + + // Check if the workspace exists + Utils::FilePath workspaceFilePath = workspaceNameToFilePath(workspace); + if (!workspaceFilePath.exists()) { + qCInfo(adsLog) << QString("Workspace doesn't exist '%1'").arg(workspaceFilePath.toString()); + return; + } + + // Finally copy the workspace to the target + QFile workspaceFile(workspaceFilePath.toString()); + if (!workspaceFile.copy(targetFileInfo.absoluteFilePath())) { + qCInfo(adsLog) << QString("Could not copy '%1' to '%2' error: %3").arg( + workspace, workspaceFilePath.toString(), workspaceFile.errorString()); + } + } + bool DockManager::write(const QString &workspace, const QByteArray &data, QString *errorString) const { - Utils::FilePath filename = workspaceNameToFileName(workspace); + Utils::FilePath fileName = workspaceNameToFilePath(workspace); QDir tmp; - tmp.mkpath(filename.toFileInfo().path()); - Utils::FileSaver fileSaver(filename.toString(), QIODevice::Text); + tmp.mkpath(fileName.toFileInfo().path()); + Utils::FileSaver fileSaver(fileName.toString(), QIODevice::Text); if (!fileSaver.hasError()) fileSaver.write(data); @@ -884,7 +983,7 @@ namespace ADS QByteArray DockManager::loadWorkspace(const QString &workspace) const { QByteArray data; - Utils::FilePath fileName = workspaceNameToFileName(workspace); + Utils::FilePath fileName = workspaceNameToFilePath(workspace); if (fileName.exists()) { QFile file(fileName.toString()); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { @@ -920,18 +1019,15 @@ namespace ADS } for (const auto &preset : presets) { - QString filename = preset; - filename.replace(" ", "_"); - filename.append(".wrk"); - - QString filePath = presetsDir.filePath(filename); + QString fileName = workspaceNameToFileName(preset); + QString filePath = presetsDir.filePath(fileName); QFile file(filePath); if (file.exists()) { - if (!file.copy(workspaceDir.filePath(filename))) { + if (!file.copy(workspaceDir.filePath(fileName))) qCInfo(adsLog) << QString("Could not copy '%1' to '%2' error: %3").arg( - filePath, workspaceDir.filePath(filename), file.errorString()); - } + filePath, workspaceDir.filePath(fileName), file.errorString()); + d->m_workspaceListDirty = true; } } @@ -946,4 +1042,22 @@ namespace ADS d->m_settings->setValue(Constants::STARTUP_WORKSPACE_SETTINGS_KEY, activeWorkspace()); } + void DockManager::notifyWidgetOrAreaRelocation(QWidget *droppedWidget) + { + if (d->m_focusController) + d->m_focusController->notifyWidgetOrAreaRelocation(droppedWidget); + } + + void DockManager::notifyFloatingWidgetDrop(FloatingDockContainer *floatingWidget) + { + if (d->m_focusController) + d->m_focusController->notifyFloatingWidgetDrop(floatingWidget); + } + + void DockManager::setDockWidgetFocused(DockWidget *dockWidget) + { + if (d->m_focusController) + d->m_focusController->setDockWidgetFocused(dockWidget); + } + } // namespace ADS |