diff --git a/src/plugins/debugger/debuggerconstants.h b/src/plugins/debugger/debuggerconstants.h index f294555c7ae..d1fd5fb39fd 100644 --- a/src/plugins/debugger/debuggerconstants.h +++ b/src/plugins/debugger/debuggerconstants.h @@ -39,7 +39,6 @@ const char C_CPPDEBUGGER[] = "Gdb Debugger"; const char C_QMLDEBUGGER[] = "Qml/JavaScript Debugger"; const char PRESET_PERSPRECTIVE_ID[] = "Debugger.Perspective.Preset"; -const char PERSPECTIVE_ID[] = "Debugger.Perspective"; // Menu Groups const char G_GENERAL[] = "Debugger.Group.General"; diff --git a/src/plugins/debugger/debuggerengine.cpp b/src/plugins/debugger/debuggerengine.cpp index 20d3a71f52a..42c17f0c635 100644 --- a/src/plugins/debugger/debuggerengine.cpp +++ b/src/plugins/debugger/debuggerengine.cpp @@ -526,11 +526,12 @@ public: void DebuggerEnginePrivate::setupViews() { - const DebuggerRunParameters &rp = m_engine->runParameters(); + const DebuggerRunParameters &rp = m_runParameters; QTC_CHECK(!m_perspective); - const QString id = Constants::PERSPECTIVE_ID + m_debuggerName + rp.displayName; - m_perspective = new Perspective(id, m_engine->displayName()); + const QString perspectiveId = "Debugger.Perspective." + m_debuggerName + '.' + rp.displayName; + m_perspective = new Perspective(perspectiveId, m_engine->displayName(), + Debugger::Constants::PRESET_PERSPRECTIVE_ID); m_progress.setProgressRange(0, 1000); FutureProgress *fp = ProgressManager::addTask(m_progress.future(), @@ -571,7 +572,10 @@ void DebuggerEnginePrivate::setupViews() this, &DebuggerEnginePrivate::resetLocation); QSettings *settings = ICore::settings(); - const QString perspectiveId = m_perspective->id(); + + auto dockId = [perspectiveId](const QString &dockname) { + return QString(dockname + '.' + perspectiveId); + }; m_modulesView = new BaseTreeView; m_modulesView->setModel(m_modulesHandler.model()); @@ -581,7 +585,7 @@ void DebuggerEnginePrivate::setupViews() m_engine, &DebuggerEngine::reloadModules, Qt::QueuedConnection); m_modulesWindow = addSearch(m_modulesView); - m_modulesWindow->setObjectName(DOCKWIDGET_MODULES + perspectiveId); + m_modulesWindow->setObjectName(dockId(DOCKWIDGET_MODULES)); m_modulesWindow->setWindowTitle(tr("&Modules")); m_registerView = new BaseTreeView; @@ -592,7 +596,7 @@ void DebuggerEnginePrivate::setupViews() m_engine, &DebuggerEngine::reloadRegisters, Qt::QueuedConnection); m_registerWindow = addSearch(m_registerView); - m_registerWindow->setObjectName(DOCKWIDGET_REGISTER + m_perspective->id()); + m_registerWindow->setObjectName(dockId(DOCKWIDGET_REGISTER)); m_registerWindow->setWindowTitle(tr("Reg&isters")); m_stackView = new BaseTreeView; @@ -600,7 +604,7 @@ void DebuggerEnginePrivate::setupViews() m_stackView->setSettings(settings, "Debugger.StackView"); m_stackView->setIconSize(QSize(10, 10)); m_stackWindow = addSearch(m_stackView); - m_stackWindow->setObjectName(DOCKWIDGET_STACK + m_perspective->id()); + m_stackWindow->setObjectName(dockId(DOCKWIDGET_STACK)); m_stackWindow->setWindowTitle(tr("&Stack")); m_sourceFilesView = new BaseTreeView; @@ -611,7 +615,7 @@ void DebuggerEnginePrivate::setupViews() m_engine, &DebuggerEngine::reloadSourceFiles, Qt::QueuedConnection); m_sourceFilesWindow = addSearch(m_sourceFilesView); - m_sourceFilesWindow->setObjectName(DOCKWIDGET_SOURCE_FILES + m_perspective->id()); + m_sourceFilesWindow->setObjectName(dockId(DOCKWIDGET_SOURCE_FILES)); m_sourceFilesWindow->setWindowTitle(tr("Source Files")); m_threadsView = new BaseTreeView; @@ -620,13 +624,13 @@ void DebuggerEnginePrivate::setupViews() m_threadsView->setSettings(settings, "Debugger.ThreadsView"); m_threadsView->setIconSize(QSize(10, 10)); m_threadsWindow = addSearch(m_threadsView); - m_threadsWindow->setObjectName(DOCKWIDGET_THREADS + m_perspective->id()); + m_threadsWindow->setObjectName(dockId(DOCKWIDGET_THREADS)); m_threadsWindow->setWindowTitle(tr("&Threads")); m_returnView = new WatchTreeView{ReturnType}; m_returnView->setModel(m_watchHandler.model()); m_returnWindow = addSearch(m_returnView); - m_returnWindow->setObjectName("CppDebugReturn" + m_perspective->id()); + m_returnWindow->setObjectName(dockId("CppDebugReturn")); m_returnWindow->setWindowTitle(tr("Locals")); m_returnWindow->setVisible(false); @@ -634,26 +638,26 @@ void DebuggerEnginePrivate::setupViews() m_localsView->setModel(m_watchHandler.model()); m_localsView->setSettings(settings, "Debugger.LocalsView"); m_localsWindow = addSearch(m_localsView); - m_localsWindow->setObjectName("CppDebugLocals" + m_perspective->id()); + m_localsWindow->setObjectName(dockId("CppDebugLocals")); m_localsWindow->setWindowTitle(tr("Locals")); m_inspectorView = new WatchTreeView{InspectType}; m_inspectorView->setModel(m_watchHandler.model()); m_inspectorView->setSettings(settings, "Debugger.LocalsView"); // sic! same as locals view. m_inspectorWindow = addSearch(m_inspectorView); - m_inspectorWindow->setObjectName("Inspector" + m_perspective->id()); + m_inspectorWindow->setObjectName(dockId("Inspector")); m_inspectorWindow->setWindowTitle(tr("Locals")); m_watchersView = new WatchTreeView{WatchersType}; m_watchersView->setModel(m_watchHandler.model()); m_watchersView->setSettings(settings, "Debugger.WatchersView"); m_watchersWindow = addSearch(m_watchersView); - m_watchersWindow->setObjectName("CppDebugWatchers" + m_perspective->id()); + m_watchersWindow->setObjectName(dockId("CppDebugWatchers")); m_watchersWindow->setWindowTitle(tr("&Expressions")); m_localsAndInspectorWindow = new LocalsAndInspectorWindow( m_localsWindow, m_inspectorWindow, m_returnWindow); - m_localsAndInspectorWindow->setObjectName(DOCKWIDGET_LOCALS_AND_INSPECTOR + m_perspective->id()); + m_localsAndInspectorWindow->setObjectName(dockId(DOCKWIDGET_LOCALS_AND_INSPECTOR)); m_localsAndInspectorWindow->setWindowTitle(m_localsWindow->windowTitle()); // Locals @@ -670,7 +674,7 @@ void DebuggerEnginePrivate::setupViews() m_breakView->setModel(m_breakHandler.model()); m_breakView->setRootIsDecorated(true); m_breakWindow = addSearch(m_breakView); - m_breakWindow->setObjectName(DOCKWIDGET_BREAK + m_perspective->id()); + m_breakWindow->setObjectName(dockId(DOCKWIDGET_BREAK)); m_breakWindow->setWindowTitle(tr("&Breakpoints")); m_perspective->addToolBarWidget(EngineManager::engineChooser()); @@ -776,7 +780,6 @@ void DebuggerEnginePrivate::setupViews() m_inspectorWindow->setFont(font); }); - m_perspective->setParentPerspective(Debugger::Constants::PRESET_PERSPRECTIVE_ID); m_perspective->addWindow(m_stackWindow, Perspective::SplitVertical, nullptr); m_perspective->addWindow(m_breakWindow, Perspective::SplitHorizontal, m_stackWindow); m_perspective->addWindow(m_threadsWindow, Perspective::AddToTab, m_breakWindow,false); diff --git a/src/plugins/debugger/debuggermainwindow.cpp b/src/plugins/debugger/debuggermainwindow.cpp index 4b0e1439d33..c76f4231688 100644 --- a/src/plugins/debugger/debuggermainwindow.cpp +++ b/src/plugins/debugger/debuggermainwindow.cpp @@ -147,12 +147,13 @@ public: QString m_id; QString m_name; - QString m_parentPerspective; + QString m_parentPerspectiveId; QVector m_dockOperations; QVector m_toolBarOperations; QPointer m_centralWidget; Perspective::Callback m_aboutToActivateCallback; QPointer m_toolButtonBox; + QString m_lastActiveSubPerspectiveId; }; class DebuggerMainWindowPrivate : public QObject @@ -162,8 +163,9 @@ public: void ensureToolBarDockExists(); - void restorePerspective(Perspective *perspective); - void loadPerspectiveHelper(Perspective *perspective, bool fromStoredSettings = true); + void selectPerspective(Perspective *perspective); + void depopulateCurrentPerspective(); + void populateCurrentPerspective(); void savePerspectiveHelper(const Perspective *perspective); void destroyPerspective(Perspective *perspective); void registerPerspective(Perspective *perspective); @@ -196,7 +198,12 @@ DebuggerMainWindowPrivate::DebuggerMainWindowPrivate(DebuggerMainWindow *parent) m_perspectiveChooser->setProperty("panelwidget", true); connect(m_perspectiveChooser, static_cast(&QComboBox::activated), this, [this](int item) { - restorePerspective(Perspective::findPerspective(m_perspectiveChooser->itemData(item).toString())); + Perspective *perspective = Perspective::findPerspective(m_perspectiveChooser->itemData(item).toString()); + QTC_ASSERT(perspective, return); + if (auto subPerspective = Perspective::findPerspective(perspective->d->m_lastActiveSubPerspectiveId)) + subPerspective->select(); + else + perspective->select(); }); } @@ -257,8 +264,8 @@ void DebuggerMainWindow::doShutdown() void DebuggerMainWindowPrivate::registerPerspective(Perspective *perspective) { m_perspectives.append(perspective); - QString parentPerspective = perspective->d->m_parentPerspective; - // Add "main" perspectives to the chooser. + QString parentPerspective = perspective->d->m_parentPerspectiveId; + // Add only "main" perspectives to the chooser. if (parentPerspective.isEmpty()) { m_perspectiveChooser->addItem(perspective->name(), perspective->id()); increaseChooserWidthIfNecessary(perspective->name()); @@ -291,8 +298,8 @@ void DebuggerMainWindowPrivate::destroyPerspective(Perspective *perspective) if (perspective == m_currentPerspective) { m_currentPerspective = nullptr; - if (!perspective->d->m_parentPerspective.isEmpty()) { - if (Perspective *parent = Perspective::findPerspective(perspective->d->m_parentPerspective)) + if (!perspective->d->m_parentPerspectiveId.isEmpty()) { + if (Perspective *parent = Perspective::findPerspective(perspective->d->m_parentPerspectiveId)) parent->select(); } } @@ -308,7 +315,20 @@ void DebuggerMainWindow::onModeChanged(Core::Id mode) { if (mode == Debugger::Constants::MODE_DEBUG) { theMainWindow->setDockActionsVisible(true); - theMainWindow->d->restorePerspective(nullptr); + Perspective *perspective = theMainWindow->d->m_currentPerspective; + if (!perspective) { + const QSettings *settings = ICore::settings(); + const QString lastPerspectiveId = settings->value(QLatin1String(LAST_PERSPECTIVE_KEY)).toString(); + perspective = Perspective::findPerspective(lastPerspectiveId); + // If we don't find a perspective with the stored name, pick any. + // This can happen e.g. when a plugin was disabled that provided + // the stored perspective, or when the save file was modified externally. + if (!perspective && !theMainWindow->d->m_perspectives.isEmpty()) + perspective = theMainWindow->d->m_perspectives.first(); + } + // There's at least the debugger preset perspective that should be found above. + QTC_ASSERT(perspective, return); + perspective->select(); } else { theMainWindow->setDockActionsVisible(false); @@ -344,7 +364,8 @@ void DebuggerMainWindow::closeEvent(QCloseEvent *) void DebuggerMainWindowPrivate::resetCurrentPerspective() { - loadPerspectiveHelper(m_currentPerspective, false); + depopulateCurrentPerspective(); + populateCurrentPerspective(); } int DebuggerMainWindowPrivate::indexInChooser(Perspective *perspective) const @@ -352,9 +373,23 @@ int DebuggerMainWindowPrivate::indexInChooser(Perspective *perspective) const return perspective ? m_perspectiveChooser->findData(perspective->d->m_id) : -1; } -void DebuggerMainWindowPrivate::restorePerspective(Perspective *perspective) +void DebuggerMainWindowPrivate::selectPerspective(Perspective *perspective) { - loadPerspectiveHelper(perspective, true); + QTC_ASSERT(perspective, return); + + depopulateCurrentPerspective(); + + m_currentPerspective = perspective; + + perspective->aboutToActivate(); + + populateCurrentPerspective(); + + QSettings *settings = ICore::settings(); + settings->beginGroup(perspective->d->m_id); + if (settings->value(QLatin1String("ToolSettingsSaved"), false).toBool()) + q->restoreSettings(settings); + settings->endGroup(); const int index = indexInChooser(m_currentPerspective); if (index != -1) @@ -460,75 +495,64 @@ QWidget *createModeWindow(const Core::Id &mode) return splitter; } -void DebuggerMainWindowPrivate::loadPerspectiveHelper(Perspective *perspective, bool fromStoredSettings) +void DebuggerMainWindowPrivate::depopulateCurrentPerspective() { // Clean up old perspective. - if (m_currentPerspective) { - savePerspectiveHelper(m_currentPerspective); - const QList allDocks = q->dockWidgets(); - for (QDockWidget *dock : allDocks) { - if (dock->property(OWNED_BY_PERSPECTIVE).toBool()) { - dock->setParent(nullptr); + savePerspectiveHelper(m_currentPerspective); + for (QDockWidget *dock : q->dockWidgets()) { + if (dock->property(OWNED_BY_PERSPECTIVE).toBool()) { + // Prevent deletion of plugin-owned widgets. + if (dock->widget()) dock->widget()->setParent(nullptr); - ActionManager::unregisterAction(dock->toggleViewAction(), - Id("Dock.").withSuffix(dock->objectName())); - delete dock; - } + ActionManager::unregisterAction(dock->toggleViewAction(), + Id("Dock.").withSuffix(dock->objectName())); + delete dock; } + } + if (m_currentPerspective) { ICore::removeAdditionalContext(m_currentPerspective->context()); QWidget *central = m_currentPerspective->centralWidget(); m_centralWidgetStack->removeWidget(central ? central : m_editorPlaceHolder); m_currentPerspective->d->destroyToolBar(); } +} - if (perspective) { - m_currentPerspective = perspective; - } else { - const QSettings *settings = ICore::settings(); - const QString lastPerspectiveId = settings->value(QLatin1String(LAST_PERSPECTIVE_KEY)).toString(); - m_currentPerspective = Perspective::findPerspective(lastPerspectiveId); - // If we don't find a perspective with the stored name, pick any. - // This can happen e.g. when a plugin was disabled that provided - // the stored perspective, or when the save file was modified externally. - if (!m_currentPerspective && !m_perspectives.isEmpty()) - m_currentPerspective = m_perspectives.first(); - } - QTC_ASSERT(m_currentPerspective, return); - - ICore::addAdditionalContext(m_currentPerspective->context()); - - m_currentPerspective->aboutToActivate(); - +void DebuggerMainWindowPrivate::populateCurrentPerspective() +{ + // Create dock widgets wrapping ther perspective's widgets. QHash dockForDockId; + for (const DockOperation &op : m_currentPerspective->d->m_dockOperations) { + QTC_ASSERT(op.widget, continue); + const QString dockId = op.widget->objectName(); + QTC_CHECK(!dockId.isEmpty()); + QTC_ASSERT(!dockForDockId.contains(dockId), continue); + QDockWidget *dock = q->addDockForWidget(op.widget); + dock->setProperty(OWNED_BY_PERSPECTIVE, true); + dockForDockId[dockId] = dock; + q->addDockWidget(op.area, dock); + + QAction *toggleViewAction = dock->toggleViewAction(); + toggleViewAction->setText(dock->windowTitle()); + + Command *cmd = ActionManager::registerAction(toggleViewAction, + Id("Dock.").withSuffix(dock->objectName()), + m_currentPerspective->context()); + cmd->setAttribute(Command::CA_Hide); + ActionManager::actionContainer(Core::Constants::M_WINDOW_VIEWS)->addAction(cmd); + } + + // Pre-arrange dock widgets. for (const DockOperation &op : m_currentPerspective->d->m_dockOperations) { QTC_ASSERT(op.widget, continue); const QString dockId = op.widget->objectName(); QDockWidget *dock = dockForDockId.value(dockId); - if (!dock) { - QTC_CHECK(!dockId.isEmpty()); - dock = q->addDockForWidget(op.widget); - dock->setProperty(OWNED_BY_PERSPECTIVE, true); - dockForDockId[dockId] = dock; - - QAction *toggleViewAction = dock->toggleViewAction(); - toggleViewAction->setText(dock->windowTitle()); - - Command *cmd = ActionManager::registerAction(toggleViewAction, - Id("Dock.").withSuffix(dock->objectName()), - m_currentPerspective->context()); - cmd->setAttribute(Command::CA_Hide); - - ActionManager::actionContainer(Core::Constants::M_WINDOW_VIEWS)->addAction(cmd); - } - // Restore parent/child relation, so that the widget hierarchy is clear. - dock->setParent(q); + QTC_ASSERT(dock, continue); if (op.operationType == Perspective::Raise) { dock->raise(); continue; } - q->addDockWidget(op.area, dock); QDockWidget *anchor = dockForDockId.value(op.anchorDockId); if (!anchor && op.area == Qt::BottomDockWidgetArea) { ensureToolBarDockExists(); @@ -555,22 +579,13 @@ void DebuggerMainWindowPrivate::loadPerspectiveHelper(Perspective *perspective, m_currentPerspective->d->showToolBar(); - if (fromStoredSettings) { - QSettings *settings = ICore::settings(); - settings->beginGroup(m_currentPerspective->d->m_id); - if (settings->value(QLatin1String("ToolSettingsSaved"), false).toBool()) - q->restoreSettings(settings); - settings->endGroup(); - } else { - // By default, show the central widget - q->showCentralWidgetAction()->setChecked(true); - } - QWidget *central = m_currentPerspective->centralWidget(); m_centralWidgetStack->addWidget(central ? central : m_editorPlaceHolder); q->showCentralWidgetAction()->setText(central ? central->windowTitle() : tr("Editor")); m_statusLabel->clear(); + + ICore::addAdditionalContext(m_currentPerspective->context()); } void DebuggerMainWindowPrivate::savePerspectiveHelper(const Perspective *perspective) @@ -587,11 +602,12 @@ void DebuggerMainWindowPrivate::savePerspectiveHelper(const Perspective *perspec // Perspective -Perspective::Perspective(const QString &id, const QString &name) +Perspective::Perspective(const QString &id, const QString &name, const QString &parentPerspectiveId) : d(new PerspectivePrivate) { d->m_id = id; d->m_name = name; + d->m_parentPerspectiveId = parentPerspectiveId; DebuggerMainWindow::ensureMainWindowExists(); theMainWindow->d->registerPerspective(this); @@ -599,8 +615,9 @@ Perspective::Perspective(const QString &id, const QString &name) Perspective::~Perspective() { - if (theMainWindow) + if (theMainWindow) { theMainWindow->d->destroyPerspective(this); + } delete d; } @@ -631,11 +648,6 @@ void Perspective::aboutToActivate() const d->m_aboutToActivateCallback(); } -void Perspective::setParentPerspective(const QString &parentPerspectiveId) -{ - d->m_parentPerspective = parentPerspectiveId; -} - void Perspective::setEnabled(bool enabled) { QTC_ASSERT(theMainWindow, return); @@ -749,13 +761,12 @@ void Perspective::addWindow(QWidget *widget, void Perspective::select() { - if (ModeManager::currentModeId() == Debugger::Constants::MODE_DEBUG && currentPerspective() == this) { - // Prevents additional show events triggering modules and register updates. - return; - } - ModeManager::activateMode(Debugger::Constants::MODE_DEBUG); - theMainWindow->d->restorePerspective(this); + theMainWindow->d->selectPerspective(this); + if (Perspective *parent = Perspective::findPerspective(d->m_parentPerspectiveId)) + parent->d->m_lastActiveSubPerspectiveId = d->m_id; + else + d->m_lastActiveSubPerspectiveId.clear(); } // ToolbarAction diff --git a/src/plugins/debugger/debuggermainwindow.h b/src/plugins/debugger/debuggermainwindow.h index 06b73ca3448..18432458c27 100644 --- a/src/plugins/debugger/debuggermainwindow.h +++ b/src/plugins/debugger/debuggermainwindow.h @@ -63,7 +63,8 @@ public: class DEBUGGER_EXPORT Perspective { public: - explicit Perspective(const QString &id, const QString &name); + Perspective(const QString &id, const QString &name, + const QString &parentPerspectiveId = QString()); ~Perspective(); enum OperationType { SplitVertical, SplitHorizontal, AddToTab, Raise }; @@ -89,7 +90,6 @@ public: void setAboutToActivateCallback(const Callback &cb); void aboutToActivate() const; - void setParentPerspective(const QString &parentPerspectiveId); void setEnabled(bool enabled); void select(); diff --git a/src/plugins/debugger/debuggerruncontrol.cpp b/src/plugins/debugger/debuggerruncontrol.cpp index df36c40bf3f..4c35b89664a 100644 --- a/src/plugins/debugger/debuggerruncontrol.cpp +++ b/src/plugins/debugger/debuggerruncontrol.cpp @@ -615,8 +615,8 @@ void DebuggerRunTool::start() return; } - m_engine->setRunTool(this); m_engine->setRunParameters(m_runParameters); + m_engine->setRunTool(this); m_engine->setCompanionEngine(m_engine2); connect(m_engine, &DebuggerEngine::requestRunControlFinish, runControl(), &RunControl::initiateFinish); @@ -644,8 +644,8 @@ void DebuggerRunTool::start() }); if (m_engine2) { - m_engine2->setRunTool(this); m_engine2->setRunParameters(m_runParameters); + m_engine2->setRunTool(this); m_engine2->setCompanionEngine(m_engine); m_engine2->setSecondaryEngine(); connect(m_engine2, &DebuggerEngine::requestRunControlFinish,