Commit 6492d164 authored by hjk's avatar hjk

Debugger: Split out re-usable parts of ex-AnalyzerMainWindow

Next steps is to re-use it for ex-DebuggerMainWindow.

Change-Id: Ic272d062f6db2e54ed62082c2a7d3a289b810a03
Reviewed-by: default avatarChristian Stenger <christian.stenger@theqtcompany.com>
parent 397e6546
......@@ -31,6 +31,8 @@
#include "analyzerruncontrol.h"
#include "../debuggerplugin.h"
#include "../debuggermainwindow.h"
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/command.h>
......@@ -70,8 +72,8 @@
#include <QMenu>
#include <QPointer>
#include <QPushButton>
#include <QSettings>
#include <QStackedWidget>
#include <QSettings>
#include <QToolButton>
#include <QVBoxLayout>
#include <QVariant>
......@@ -81,6 +83,8 @@ using namespace Utils;
using namespace Core::Constants;
using namespace Analyzer::Constants;
using namespace ProjectExplorer;
using namespace Debugger;
using namespace Debugger::Internal;
namespace Analyzer {
......@@ -250,8 +254,6 @@ class AnalyzerManagerPrivate : public QObject
{
Q_DECLARE_TR_FUNCTIONS(Analyzer::AnalyzerManager)
public:
typedef QHash<QString, QVariant> FancyMainWindowSettings;
AnalyzerManagerPrivate(AnalyzerManager *qq);
~AnalyzerManagerPrivate();
......@@ -273,50 +275,34 @@ public:
void selectAction(Id actionId);
void handleToolStarted();
void handleToolFinished();
void savePerspective(Id perspectiveId);
void restorePerspective(Id perspectiveId, bool fromStoredSettings);
void modeChanged(IMode *mode);
void resetLayout();
void updateRunActions();
const ActionDescription *findAction(Id actionId) const;
const Perspective *findPerspective(Id perspectiveId) const;
const Id currentPerspectiveId() const;
public:
AnalyzerManager *q;
Internal::AnalyzerMode *m_mode = 0;
bool m_isRunning = false;
FancyMainWindow *m_mainWindow = 0;
Core::Id m_currentActionId;
QHash<Id, QAction *> m_actions;
QList<ActionDescription> m_descriptions;
QAction *m_startAction = 0;
QAction *m_stopAction = 0;
ActionContainer *m_menu = 0;
QComboBox *m_toolBox;
QStackedWidget *m_controlsStackWidget;
QStackedWidget *m_statusLabelsStackWidget;
QHash<Id, QDockWidget *> m_dockForDockId;
QList<Perspective> m_perspectives;
QHash<Id, QWidget *> m_controlsWidgetForPerspective;
QHash<Id, StatusLabel *> m_statusLabelForPerspective;
QSet<Id> m_defaultSettings;
// list of dock widgets to prevent memory leak
typedef QPointer<QDockWidget> DockPtr;
QList<DockPtr> m_dockWidgets;
MainWindowBase *m_mainWindow;
};
AnalyzerManagerPrivate::AnalyzerManagerPrivate(AnalyzerManager *qq):
q(qq),
m_toolBox(new QComboBox),
m_controlsStackWidget(new QStackedWidget),
m_statusLabelsStackWidget(new QStackedWidget)
{
m_toolBox->setObjectName(QLatin1String("AnalyzerManagerToolBox"));
m_toolBox->insertSeparator(0);
connect(m_toolBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated), this, [this](int item) {
selectAction(Id::fromSetting(m_toolBox->itemData(item)));
q(qq), m_mainWindow(new MainWindowBase)
{
QComboBox *toolBox = m_mainWindow->toolBox();
toolBox->setObjectName(QLatin1String("AnalyzerManagerToolBox"));
toolBox->insertSeparator(0);
connect(toolBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated), this, [this, toolBox](int item) {
selectAction(Id::fromSetting(toolBox->itemData(item)));
});
setupActions();
......@@ -327,12 +313,6 @@ AnalyzerManagerPrivate::AnalyzerManagerPrivate(AnalyzerManager *qq):
AnalyzerManagerPrivate::~AnalyzerManagerPrivate()
{
// as we have to setParent(0) on dock widget that are not selected,
// we keep track of all and make sure we don't leak any
foreach (const DockPtr &ptr, m_dockWidgets) {
if (ptr)
delete ptr.data();
}
}
void AnalyzerManagerPrivate::setupActions()
......@@ -436,12 +416,12 @@ static QToolButton *toolButton(QAction *action)
void AnalyzerManagerPrivate::createModeMainWindow()
{
m_mainWindow = new FancyMainWindow();
m_mainWindow->setObjectName(QLatin1String("AnalyzerManagerMainWindow"));
m_mainWindow->setDocumentMode(true);
m_mainWindow->setDockNestingEnabled(true);
m_mainWindow->setDockActionsVisible(false);
connect(m_mainWindow, &FancyMainWindow::resetLayout, this, &AnalyzerManagerPrivate::resetLayout);
m_mainWindow->setSettingsName(QLatin1String("AnalyzerViewSettings_"));
m_mainWindow->setLastSettingsName(QLatin1String(Internal::LAST_ACTIVE_TOOL));
connect(m_mainWindow, &FancyMainWindow::resetLayout,
this, &AnalyzerManagerPrivate::resetLayout);
auto editorHolderLayout = new QVBoxLayout;
editorHolderLayout->setMargin(0);
......@@ -467,9 +447,9 @@ void AnalyzerManagerPrivate::createModeMainWindow()
analyzeToolBarLayout->addWidget(toolButton(m_startAction));
analyzeToolBarLayout->addWidget(toolButton(m_stopAction));
analyzeToolBarLayout->addWidget(new StyledSeparator);
analyzeToolBarLayout->addWidget(m_toolBox);
analyzeToolBarLayout->addWidget(m_controlsStackWidget);
analyzeToolBarLayout->addWidget(m_statusLabelsStackWidget);
analyzeToolBarLayout->addWidget(m_mainWindow->toolBox());
analyzeToolBarLayout->addWidget(m_mainWindow->controlsStack());
analyzeToolBarLayout->addWidget(m_mainWindow->statusLabelsStack());
analyzeToolBarLayout->addStretch();
auto dock = new QDockWidget(tr("Analyzer Toolbar"));
......@@ -552,14 +532,6 @@ const ActionDescription *AnalyzerManagerPrivate::findAction(Id actionId) const
return 0;
}
const Perspective *AnalyzerManagerPrivate::findPerspective(Id perspectiveId) const
{
foreach (const Perspective &perspective, m_perspectives)
if (perspective.id() == perspectiveId)
return &perspective;
return 0;
}
const Id AnalyzerManagerPrivate::currentPerspectiveId() const
{
const ActionDescription *action = findAction(m_currentActionId);
......@@ -575,41 +547,18 @@ void AnalyzerManagerPrivate::selectAction(Id actionId)
// Clean up old tool.
Id currentPerspective = currentPerspectiveId();
if (currentPerspective.isValid()) {
savePerspective(currentPerspective);
const Perspective *perspective = findPerspective(currentPerspective);
QTC_ASSERT(perspective, return);
foreach (Id dockId, perspective->docks()) {
QDockWidget *dockWidget = m_dockForDockId.value(dockId);
QTC_ASSERT(dockWidget, continue);
m_mainWindow->removeDockWidget(dockWidget);
dockWidget->hide();
// Prevent saveState storing the data of the wrong children.
dockWidget->setParent(0);
}
}
m_mainWindow->closePerspective(currentPerspective);
// Now change the tool.
m_currentActionId = actionId;
Id perspectiveId = desc->perspectiveId();
if (!m_defaultSettings.contains(perspectiveId)) {
QWidget *widget = desc->createWidget();
QTC_CHECK(widget);
m_defaultSettings.insert(perspectiveId);
QTC_CHECK(!m_controlsWidgetForPerspective.contains(perspectiveId));
m_controlsWidgetForPerspective[perspectiveId] = widget;
m_controlsStackWidget->addWidget(widget);
StatusLabel * const toolStatusLabel = new StatusLabel;
m_statusLabelForPerspective[perspectiveId] = toolStatusLabel;
m_statusLabelsStackWidget->addWidget(toolStatusLabel);
}
restorePerspective(desc->perspectiveId(), true);
m_mainWindow->restorePerspective(desc->perspectiveId(),
[desc] { return desc->createWidget(); },
true);
const int toolboxIndex = m_toolBox->findText(desc->text());
const int toolboxIndex = m_mainWindow->toolBox()->findText(desc->text());
QTC_ASSERT(toolboxIndex >= 0, return);
m_toolBox->setCurrentIndex(toolboxIndex);
m_mainWindow->toolBox()->setCurrentIndex(toolboxIndex);
updateRunActions();
}
......@@ -625,15 +574,15 @@ void AnalyzerManagerPrivate::addAction(const ActionDescription &desc)
int index = -1;
if (desc.menuGroup() == Constants::G_ANALYZER_REMOTE_TOOLS) {
index = m_toolBox->count();
index = m_mainWindow->toolBox()->count();
} else if (desc.menuGroup() == Constants::G_ANALYZER_TOOLS) {
for (int i = m_toolBox->count(); --i >= 0; )
if (m_toolBox->itemText(i).isEmpty())
for (int i = m_mainWindow->toolBox()->count(); --i >= 0; )
if (m_mainWindow->toolBox()->itemText(i).isEmpty())
index = i;
}
if (index >= 0)
m_toolBox->insertItem(index, desc.text(), desc.actionId().toSetting());
m_mainWindow->toolBox()->insertItem(index, desc.text(), desc.actionId().toSetting());
Id menuGroup = desc.menuGroup();
if (menuGroup.isValid()) {
......@@ -661,63 +610,6 @@ void AnalyzerManagerPrivate::handleToolFinished()
updateRunActions();
}
void AnalyzerManagerPrivate::restorePerspective(Id perspectiveId, bool fromStoredSettings)
{
QTC_ASSERT(m_mainWindow, return);
if (!perspectiveId.isValid())
return;
const Perspective *perspective = findPerspective(perspectiveId);
QTC_ASSERT(perspective, return);
foreach (const Perspective::Split &split, perspective->splits()) {
QDockWidget *dock = m_dockForDockId.value(split.dockId);
m_mainWindow->addDockWidget(split.area, dock);
QDockWidget *existing = m_dockForDockId.value(split.existing);
if (!existing && split.area == Qt::BottomDockWidgetArea)
existing = m_mainWindow->toolBarDockWidget();
if (existing) {
switch (split.splitType) {
case Perspective::AddToTab:
m_mainWindow->tabifyDockWidget(existing, dock);
break;
case Perspective::SplitHorizontal:
m_mainWindow->splitDockWidget(existing, dock, Qt::Horizontal);
break;
case Perspective::SplitVertical:
m_mainWindow->splitDockWidget(existing, dock, Qt::Vertical);
break;
}
}
if (!split.visibleByDefault)
dock->hide();
}
if (fromStoredSettings) {
QSettings *settings = ICore::settings();
settings->beginGroup(QLatin1String("AnalyzerViewSettings_") + perspectiveId.toString());
if (settings->value(QLatin1String("ToolSettingsSaved"), false).toBool())
m_mainWindow->restoreSettings(settings);
settings->endGroup();
}
QTC_CHECK(m_controlsWidgetForPerspective.contains(perspectiveId));
m_controlsStackWidget->setCurrentWidget(m_controlsWidgetForPerspective.value(perspectiveId));
m_statusLabelsStackWidget->setCurrentWidget(m_statusLabelForPerspective.value(perspectiveId));
}
void AnalyzerManagerPrivate::savePerspective(Id perspectiveId)
{
QTC_ASSERT(m_mainWindow, return);
QSettings *settings = ICore::settings();
settings->beginGroup(QLatin1String("AnalyzerViewSettings_") + perspectiveId.toString());
m_mainWindow->saveSettings(settings);
settings->setValue(QLatin1String("ToolSettingsSaved"), true);
settings->endGroup();
settings->setValue(QLatin1String(Internal::LAST_ACTIVE_TOOL), perspectiveId.toString());
}
void AnalyzerManagerPrivate::updateRunActions()
{
QString disabledReason;
......@@ -731,7 +623,7 @@ void AnalyzerManagerPrivate::updateRunActions()
m_startAction->setEnabled(enabled);
m_startAction->setToolTip(disabledReason);
m_toolBox->setEnabled(!m_isRunning);
m_mainWindow->toolBox()->setEnabled(!m_isRunning);
m_stopAction->setEnabled(m_isRunning);
foreach (const ActionDescription &desc, m_descriptions) {
......@@ -764,7 +656,7 @@ AnalyzerManager::~AnalyzerManager()
void AnalyzerManager::shutdown()
{
d->savePerspective(d->currentPerspectiveId());
d->m_mainWindow->savePerspective(d->currentPerspectiveId());
}
void AnalyzerManager::addAction(const ActionDescription &desc)
......@@ -775,12 +667,11 @@ void AnalyzerManager::addAction(const ActionDescription &desc)
QDockWidget *AnalyzerManager::createDockWidget(QWidget *widget, Id dockId)
{
QTC_ASSERT(!widget->objectName().isEmpty(), return 0);
QDockWidget *dockWidget = d->m_mainWindow->addDockForWidget(widget);
d->m_dockWidgets.append(AnalyzerManagerPrivate::DockPtr(dockWidget));
d->m_dockForDockId[dockId] = dockWidget;
QDockWidget *dockWidget = d->m_mainWindow->createDockWidget(widget, dockId);
QAction *toggleViewAction = dockWidget->toggleViewAction();
toggleViewAction->setText(dockWidget->windowTitle());
Command *cmd = ActionManager::registerAction(toggleViewAction,
Id("Analyzer.").withSuffix(dockWidget->objectName()));
cmd->setAttribute(Command::CA_Hide);
......@@ -800,7 +691,7 @@ void Perspective::addDock(Id dockId, Id existing, SplitType splitType,
void AnalyzerManager::addPerspective(const Perspective &perspective)
{
d->m_perspectives.append(perspective);
d->m_mainWindow->addPerspective(perspective);
}
void AnalyzerManager::selectAction(Id actionId, bool alsoRunIt)
......@@ -819,19 +710,19 @@ void AnalyzerManager::enableMainWindow(bool on)
void AnalyzerManagerPrivate::resetLayout()
{
restorePerspective(currentPerspectiveId(), false);
d->m_mainWindow->restorePerspective(currentPerspectiveId(),
std::function<QWidget *()>(),
false);
}
void AnalyzerManager::showStatusMessage(Id perspective, const QString &message, int timeoutMS)
{
StatusLabel * const statusLabel = d->m_statusLabelForPerspective.value(perspective);
QTC_ASSERT(statusLabel, return);
statusLabel->showStatusMessage(message, timeoutMS);
d->m_mainWindow->showStatusMessage(perspective, message, timeoutMS);
}
void AnalyzerManager::showPermanentStatusMessage(Id perspective, const QString &message)
{
showStatusMessage(perspective, message, -1);
d->m_mainWindow->showStatusMessage(perspective, message, -1);
}
void AnalyzerManager::showMode()
......
......@@ -30,6 +30,8 @@
#include "analyzerbase_global.h"
#include "analyzerconstants.h"
#include "../debuggermainwindow.h"
#include <coreplugin/id.h>
#include <projectexplorer/projectexplorerconstants.h>
......@@ -142,41 +144,6 @@ private:
ToolPreparer m_toolPreparer;
};
class ANALYZER_EXPORT Perspective
{
public:
enum SplitType { SplitVertical, SplitHorizontal, AddToTab };
struct Split {
Split() = default;
Split(Core::Id e, Core::Id d, SplitType t, bool v, Qt::DockWidgetArea a)
: existing(e), dockId(d), splitType(t), visibleByDefault(v), area(a)
{}
Core::Id existing;
Core::Id dockId;
SplitType splitType;
bool visibleByDefault;
Qt::DockWidgetArea area;
};
typedef QVector<Split> Splits;
Perspective(Core::Id id = Core::Id()) : m_id(id) {}
Core::Id id() const { return m_id; }
void addDock(Core::Id dockId, Core::Id existing, SplitType splitType,
bool visibleByDefault = true,
Qt::DockWidgetArea area = Qt::BottomDockWidgetArea);
Splits splits() const { return m_splits; }
QList<Core::Id> docks() const { return m_docks; }
private:
Core::Id m_id;
QList<Core::Id> m_docks;
Splits m_splits;
};
// FIXME: Merge with AnalyzerPlugin.
class ANALYZER_EXPORT AnalyzerManager : public QObject
{
......
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "debuggermainwindow.h"
#include <coreplugin/icore.h>
#include <utils/qtcassert.h>
#include <QComboBox>
#include <QDockWidget>
#include <QStackedWidget>
using namespace Analyzer;
using namespace Core;
using namespace Utils;
namespace Debugger {
namespace Internal {
MainWindowBase::MainWindowBase()
{
m_controlsStackWidget = new QStackedWidget;
m_statusLabelsStackWidget= new QStackedWidget;
m_toolBox = new QComboBox;
setDockNestingEnabled(true);
setDockActionsVisible(false);
setDocumentMode(true);
}
MainWindowBase::~MainWindowBase()
{
// as we have to setParent(0) on dock widget that are not selected,
// we keep track of all and make sure we don't leak any
foreach (const DockPtr &ptr, m_dockWidgets) {
if (ptr)
delete ptr.data();
}
}
void MainWindowBase::addPerspective(const Perspective &perspective)
{
m_perspectives.append(perspective);
}
void MainWindowBase::showStatusMessage(Id perspective, const QString &message, int timeoutMS)
{
StatusLabel *statusLabel = m_statusLabelForPerspective.value(perspective);
QTC_ASSERT(statusLabel, return);
statusLabel->showStatusMessage(message, timeoutMS);
}
void MainWindowBase::restorePerspective(Id perspectiveId,
std::function<QWidget *()> creator,
bool fromStoredSettings)
{
if (!perspectiveId.isValid())
return;
if (!m_defaultSettings.contains(perspectiveId) && creator) {
QWidget *widget = creator();
QTC_CHECK(widget);
m_defaultSettings.insert(perspectiveId);
QTC_CHECK(!m_controlsWidgetForPerspective.contains(perspectiveId));
m_controlsWidgetForPerspective[perspectiveId] = widget;
m_controlsStackWidget->addWidget(widget);
StatusLabel * const toolStatusLabel = new StatusLabel;
m_statusLabelForPerspective[perspectiveId] = toolStatusLabel;
m_statusLabelsStackWidget->addWidget(toolStatusLabel);
}
const Perspective *perspective = findPerspective(perspectiveId);
QTC_ASSERT(perspective, return);
foreach (const Perspective::Split &split, perspective->splits()) {
QDockWidget *dock = m_dockForDockId.value(split.dockId);
addDockWidget(split.area, dock);
QDockWidget *existing = m_dockForDockId.value(split.existing);
if (!existing && split.area == Qt::BottomDockWidgetArea)
existing = toolBarDockWidget();
if (existing) {
switch (split.splitType) {
case Perspective::AddToTab:
tabifyDockWidget(existing, dock);
break;
case Perspective::SplitHorizontal:
splitDockWidget(existing, dock, Qt::Horizontal);
break;
case Perspective::SplitVertical:
splitDockWidget(existing, dock, Qt::Vertical);
break;
}
}
if (!split.visibleByDefault)
dock->hide();
}
if (fromStoredSettings) {
QSettings *settings = ICore::settings();
settings->beginGroup(m_settingsName + perspectiveId.toString());
if (settings->value(QLatin1String("ToolSettingsSaved"), false).toBool())
restoreSettings(settings);
settings->endGroup();
}
QTC_CHECK(m_controlsWidgetForPerspective.contains(perspectiveId));
m_controlsStackWidget->setCurrentWidget(m_controlsWidgetForPerspective.value(perspectiveId));
m_statusLabelsStackWidget->setCurrentWidget(m_statusLabelForPerspective.value(perspectiveId));
}
void MainWindowBase::closePerspective(Id perspectiveId)
{
if (!perspectiveId.isValid())
return;
savePerspective(perspectiveId);
const Perspective *perspective = findPerspective(perspectiveId);
QTC_ASSERT(perspective, return);
foreach (Id dockId, perspective->docks()) {
QDockWidget *dockWidget = m_dockForDockId.value(dockId);
QTC_ASSERT(dockWidget, continue);
removeDockWidget(dockWidget);
dockWidget->hide();
// Prevent saveState storing the data of the wrong children.
dockWidget->setParent(0);
}
}
const Perspective *MainWindowBase::findPerspective(Id perspectiveId) const
{
foreach (const Perspective &perspective, m_perspectives)
if (perspective.id() == perspectiveId)
return &perspective;
return 0;
}
void MainWindowBase::savePerspective(Id perspectiveId)
{
QSettings *settings = ICore::settings();
settings->beginGroup(m_settingsName + perspectiveId.toString());
saveSettings(settings);
settings->setValue(QLatin1String("ToolSettingsSaved"), true);
settings->endGroup();
settings->setValue(m_lastSettingsName, perspectiveId.toString());
}
QDockWidget *MainWindowBase::createDockWidget(QWidget *widget, Id dockId)
{
QTC_ASSERT(!widget->objectName().isEmpty(), return 0);
QDockWidget *dockWidget = addDockForWidget(widget);
m_dockWidgets.append(MainWindowBase::DockPtr(dockWidget));
m_dockForDockId[dockId] = dockWidget;
return dockWidget;
}
QString MainWindowBase::settingsName() const
{
return m_settingsName;
}
void MainWindowBase::setSettingsName(const QString &settingsName)
{
m_settingsName = settingsName;
}
QString MainWindowBase::lastSettingsName() const
{
return m_lastSettingsName;
}
void MainWindowBase::setLastSettingsName(const QString &lastSettingsName)
{
m_lastSettingsName = lastSettingsName;
}
} // Internal
} // Debugger