summarylogtreecommitdiffstats
diff options
context:
space:
mode:
authorAaron Barany2019-06-01 14:23:59 -0700
committerAaron Barany2019-06-01 14:23:59 -0700
commitdb4191e8398af97de44d7cb87f0e60cb5e1643c6 (patch)
tree842471f3109d7c879f66afe3a45ff2e20b1e37bd
parentf2b7caac497c84db2667c3c25f82dedf34a576ac (diff)
downloadaur-db4191e8398af97de44d7cb87f0e60cb5e1643c6.tar.gz
Updated to 4.9.1.
Theme fixes this package was originally created for have been applied to the 4.9 release. This package has been re-purposed to apply a patch to fix EXTREMELY annoying debugger layout bugs that were introduced in 4.9.
-rw-r--r--.SRCINFO33
-rw-r--r--PKGBUILD57
-rw-r--r--qtcreator-clang-plugins.patch44
-rw-r--r--qtcreator-clazy-1.5.patch45
-rw-r--r--qtcreator-cmake-edit-fix.patch34
-rw-r--r--qtcreator-cmake-fail-target-fix.patch29
-rw-r--r--qtcreator-debugger-columns-fix.patch343
-rw-r--r--qtcreator-debugger-layout.patch1715
-rw-r--r--qtcreator-occurrences-fix.patch104
-rw-r--r--qtcreator-preload-plugins.patch21
-rw-r--r--qtcreator-theme-fixes.patch308
11 files changed, 1822 insertions, 911 deletions
diff --git a/.SRCINFO b/.SRCINFO
index 6d20f5f47d08..54585768cc42 100644
--- a/.SRCINFO
+++ b/.SRCINFO
@@ -1,14 +1,13 @@
pkgbase = qtcreator-fixed-themes
- pkgdesc = Lightweight, cross-platform integrated development environment, with fixes applied for various themes and other bug fixes
- pkgver = 4.8.2
- pkgrel = 2
+ pkgdesc = Lightweight, cross-platform integrated development environment, with theme and bug fixes applied
+ pkgver = 4.9.1
+ pkgrel = 1
url = https://www.qt.io
arch = x86_64
license = LGPL
- makedepends = git
- makedepends = mesa
makedepends = llvm
makedepends = python
+ makedepends = patchelf
depends = qt5-tools
depends = qt5-quickcontrols
depends = qt5-quickcontrols2
@@ -16,6 +15,8 @@ pkgbase = qtcreator-fixed-themes
depends = clang=8.0.0
depends = qbs
depends = clazy
+ depends = syntax-highlighting
+ depends = desktop-file-utils
optdepends = qt5-doc: integrated Qt documentation
optdepends = qt5-examples: welcome page examples
optdepends = qt5-translations: for other languages
@@ -28,20 +29,14 @@ pkgbase = qtcreator-fixed-themes
optdepends = valgrind: analyze support
conflicts = qtcreator
options = docs
- source = https://download.qt.io/official_releases/qtcreator/4.8/4.8.2/qt-creator-opensource-src-4.8.2.tar.xz
- source = qtcreator-clang-plugins.patch
- source = qtcreator-theme-fixes.patch
- source = qtcreator-occurrences-fix.patch
- source = qtcreator-debugger-columns-fix.patch
- source = qtcreator-cmake-fail-target-fix.patch
- source = qtcreator-cmake-edit-fix.patch
- sha256sums = a8257daf39f6025c8523285dc73fd6b66645f3ff071e112b484325966eee0c92
- sha256sums = 34ea74698ddff9925e06bff6b4c995bf93488d1104e8cc517bcfdd621effb428
- sha256sums = bf0f8e88d0fa628d24f59eaf1f359873926998dde442e3bcbd56afcdd6eec7fa
- sha256sums = 640c4c1607f9ee867e2445ad576697b9b0d3c9a64ae6589c1b99ea4f1d7e3481
- sha256sums = cf378a8b591a10646ad89d101375d8b04844c76a83d6c9c960036ba6a3b122e3
- sha256sums = df22bfe38bf6dd54b64d9ec0e78873a43e570eb490faf2a247aae7fd44e3d05e
- sha256sums = 5f002e93717d99a23ed94842567caa35f5cddfac317bddf29e7a677fb6db61a3
+ source = https://download.qt.io/official_releases/qtcreator/4.9/4.9.1/qt-creator-opensource-src-4.9.1.tar.xz
+ source = qtcreator-clazy-1.5.patch
+ source = qtcreator-preload-plugins.patch
+ source = qtcreator-debugger-layout.patch
+ sha256sums = 79b8228d0871927837681e6af9ab91e3ea28154cecfba317f9c0e56246b8ad81
+ sha256sums = 1f6998fea92b9a157f42cca783839ce95f70ccc667027078b7881cbb253838f0
+ sha256sums = 150c444e76ec969fc8765774b648984037829623300d0ce9d41a915b2afa792d
+ sha256sums = 6000452635f8c8f0cd21d1cc8d484821f4d0f8fc36afa744de5c2a3fdd1a5e9c
pkgname = qtcreator-fixed-themes
diff --git a/PKGBUILD b/PKGBUILD
index bda8de84b413..79f9b7428fbe 100644
--- a/PKGBUILD
+++ b/PKGBUILD
@@ -10,15 +10,15 @@
# Contributor: delor <bartekpiech gmail com>
pkgname=qtcreator-fixed-themes
-pkgver=4.8.2
+pkgver=4.9.1
_clangver=8.0.0
-pkgrel=2
-pkgdesc='Lightweight, cross-platform integrated development environment, with fixes applied for various themes and other bug fixes'
+pkgrel=1
+pkgdesc='Lightweight, cross-platform integrated development environment, with theme and bug fixes applied'
arch=(x86_64)
url='https://www.qt.io'
license=(LGPL)
-depends=(qt5-tools qt5-quickcontrols qt5-quickcontrols2 qt5-webengine clang=$_clangver qbs clazy)
-makedepends=(git mesa llvm python)
+depends=(qt5-tools qt5-quickcontrols qt5-quickcontrols2 qt5-webengine clang=$_clangver qbs clazy syntax-highlighting desktop-file-utils)
+makedepends=(llvm python patchelf)
conflicts=(qtcreator)
options=(docs)
optdepends=('qt5-doc: integrated Qt documentation'
@@ -32,19 +32,13 @@ optdepends=('qt5-doc: integrated Qt documentation'
'bzr: bazaar support'
'valgrind: analyze support')
source=("https://download.qt.io/official_releases/qtcreator/${pkgver%.*}/$pkgver/qt-creator-opensource-src-$pkgver.tar.xz"
- qtcreator-clang-plugins.patch
- qtcreator-theme-fixes.patch
- qtcreator-occurrences-fix.patch
- qtcreator-debugger-columns-fix.patch
- qtcreator-cmake-fail-target-fix.patch
- qtcreator-cmake-edit-fix.patch)
-sha256sums=('a8257daf39f6025c8523285dc73fd6b66645f3ff071e112b484325966eee0c92'
- '34ea74698ddff9925e06bff6b4c995bf93488d1104e8cc517bcfdd621effb428'
- 'bf0f8e88d0fa628d24f59eaf1f359873926998dde442e3bcbd56afcdd6eec7fa'
- '640c4c1607f9ee867e2445ad576697b9b0d3c9a64ae6589c1b99ea4f1d7e3481'
- 'cf378a8b591a10646ad89d101375d8b04844c76a83d6c9c960036ba6a3b122e3'
- 'df22bfe38bf6dd54b64d9ec0e78873a43e570eb490faf2a247aae7fd44e3d05e'
- '5f002e93717d99a23ed94842567caa35f5cddfac317bddf29e7a677fb6db61a3')
+ qtcreator-clazy-1.5.patch
+ qtcreator-preload-plugins.patch
+ qtcreator-debugger-layout.patch)
+sha256sums=('79b8228d0871927837681e6af9ab91e3ea28154cecfba317f9c0e56246b8ad81'
+ '1f6998fea92b9a157f42cca783839ce95f70ccc667027078b7881cbb253838f0'
+ '150c444e76ec969fc8765774b648984037829623300d0ce9d41a915b2afa792d'
+ '6000452635f8c8f0cd21d1cc8d484821f4d0f8fc36afa744de5c2a3fdd1a5e9c')
prepare() {
mkdir -p build
@@ -52,27 +46,27 @@ prepare() {
cd qt-creator-opensource-src-$pkgver
# fix hardcoded libexec path
sed -e 's|libexec\/qtcreator|lib\/qtcreator|g' -i qtcreator.pri
+ sed -e 's|libexec|lib|g' -i src/tools/tools.pro
# use system qbs
rm -r src/shared/qbs
- # Load analyzer plugins on demand, since upstream clang doesn't link to all plugins
+ # Adapt to clazy 1.5 plugin rename
+ patch -p1 -i ../qtcreator-clazy-1.5.patch
+ # Preload analyzer plugins, since upstream clang doesn't link to all plugins
# see http://code.qt.io/cgit/clang/clang.git/commit/?id=7f349701d3ea0c47be3a43e265699dddd3fd55cf
# and https://bugs.archlinux.org/task/59492
- patch -p1 -i ../qtcreator-clang-plugins.patch
- # Theme fixes
- patch -p1 -i ../qtcreator-theme-fixes.patch
- patch -p1 -i ../qtcreator-occurrences-fix.patch
- # Fix broken sizing for debugger columns.
- patch -p1 -i ../qtcreator-debugger-columns-fix.patch
- # Fixes for CMake integration
- patch -p1 -i ../qtcreator-cmake-fail-target-fix.patch
- patch -p1 -i ../qtcreator-cmake-edit-fix.patch
+ patch -p1 -i ../qtcreator-preload-plugins.patch
+ # Fixes for debugger layout.
+ patch -p1 -i ../qtcreator-debugger-layout.patch
}
build() {
cd build
- qmake LLVM_INSTALL_DIR=/usr QBS_INSTALL_DIR=/usr CONFIG+=journald QMAKE_CFLAGS_ISYSTEM=-I \
- DEFINES+=QBS_ENABLE_PROJECT_FILE_UPDATES "$srcdir"/qt-creator-opensource-src-$pkgver/qtcreator.pro
+ qmake LLVM_INSTALL_DIR=/usr QBS_INSTALL_DIR=/usr \
+ KSYNTAXHIGHLIGHTING_LIB_DIR=/usr/lib KSYNTAXHIGHLIGHTING_INCLUDE_DIR=/usr/include/KF5/KSyntaxHighlighting \
+ CONFIG+=journald QMAKE_CFLAGS_ISYSTEM=-I \
+ DEFINES+=QBS_ENABLE_PROJECT_FILE_UPDATES \
+ "$srcdir"/qt-creator-opensource-src-$pkgver/qtcreator.pro
make
make docs
}
@@ -84,4 +78,7 @@ package() {
make INSTALL_ROOT="$pkgdir/usr/" install_docs
install -Dm644 "$srcdir"/qt-creator-opensource-src-$pkgver/LICENSE.GPL3-EXCEPT "$pkgdir"/usr/share/licenses/qtcreator/LICENSE.GPL3-EXCEPT
+
+# Link clazy plugin explicitely
+ patchelf --add-needed ClazyPlugin.so "$pkgdir"/usr/lib/qtcreator/clangbackend
}
diff --git a/qtcreator-clang-plugins.patch b/qtcreator-clang-plugins.patch
deleted file mode 100644
index 5dc5b567afa4..000000000000
--- a/qtcreator-clang-plugins.patch
+++ /dev/null
@@ -1,44 +0,0 @@
-diff --git a/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp b/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp
-index 25054f14ec..b0e17c3260 100644
---- a/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp
-+++ b/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp
-@@ -524,6 +524,7 @@ private:
- if (tidyMode == Mode::Disabled)
- return;
-
-+ addXclangArg("-load", "libclangTidyPlugin.so");
- addXclangArg("-add-plugin", "clang-tidy");
-
- if (tidyMode == Mode::File)
-@@ -539,7 +540,8 @@ private:
- if (checks.isEmpty())
- return;
-
-- addXclangArg("-add-plugin", "clang-lazy");
-+ addXclangArg("-load", "ClazyPlugin.so");
-+ addXclangArg("-add-plugin", "clazy");
- addXclangArg("-plugin-arg-clang-lazy", "enable-all-fixits");
- addXclangArg("-plugin-arg-clang-lazy", "no-autowrite-fixits");
- addXclangArg("-plugin-arg-clang-lazy", checks);
-diff --git a/src/plugins/clangtools/clangtidyclazyrunner.cpp b/src/plugins/clangtools/clangtidyclazyrunner.cpp
-index d91724392e..75e1692f49 100644
---- a/src/plugins/clangtools/clangtidyclazyrunner.cpp
-+++ b/src/plugins/clangtools/clangtidyclazyrunner.cpp
-@@ -83,6 +83,7 @@ QStringList ClangTidyClazyRunner::constructCommandLineArguments(const QStringLis
-
- const ClangDiagnosticConfig::TidyMode tidyMode = m_diagnosticConfig.clangTidyMode();
- if (tidyMode != ClangDiagnosticConfig::TidyMode::Disabled) {
-+ addXclangArg(arguments, QString("-load"), QString("libclangTidyPlugin.so"));
- addXclangArg(arguments, QString("-add-plugin"), QString("clang-tidy"));
- if (tidyMode != ClangDiagnosticConfig::TidyMode::File) {
- const QString tidyChecks = m_diagnosticConfig.clangTidyChecks();
-@@ -92,7 +93,8 @@ QStringList ClangTidyClazyRunner::constructCommandLineArguments(const QStringLis
-
- const QString clazyChecks = m_diagnosticConfig.clazyChecks();
- if (!clazyChecks.isEmpty()) {
-- addXclangArg(arguments, QString("-add-plugin"), QString("clang-lazy"));
-+ addXclangArg(arguments, QString("-load"), QString("ClazyPlugin.so"));
-+ addXclangArg(arguments, QString("-add-plugin"), QString("clazy"));
- addXclangArg(arguments, QString("-plugin-arg-clang-lazy"), QString("enable-all-fixits"));
- addXclangArg(arguments, QString("-plugin-arg-clang-lazy"), QString("no-autowrite-fixits"));
- addXclangArg(arguments, QString("-plugin-arg-clang-lazy"), m_diagnosticConfig.clazyChecks());
diff --git a/qtcreator-clazy-1.5.patch b/qtcreator-clazy-1.5.patch
new file mode 100644
index 000000000000..ce9d2cc0ef69
--- /dev/null
+++ b/qtcreator-clazy-1.5.patch
@@ -0,0 +1,45 @@
+diff --git a/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp b/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp
+index 706c5101a3..dbfaeb8457 100644
+--- a/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp
++++ b/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp
+@@ -527,14 +528,14 @@ private:
+ return;
+
+ m_options.append(CppTools::XclangArgs({"-add-plugin",
+- "clang-lazy",
+- "-plugin-arg-clang-lazy",
++ "clazy",
++ "-plugin-arg-clazy",
+ "enable-all-fixits",
+- "-plugin-arg-clang-lazy",
++ "-plugin-arg-clazy",
+ "no-autowrite-fixits",
+- "-plugin-arg-clang-lazy",
++ "-plugin-arg-clazy",
+ checks,
+- "-plugin-arg-clang-lazy",
++ "-plugin-arg-clazy",
+ "ignore-included-files"}));
+ }
+
+diff --git a/src/plugins/clangtools/clangtidyclazyrunner.cpp b/src/plugins/clangtools/clangtidyclazyrunner.cpp
+index a580704243..7a8740a5cc 100644
+--- a/src/plugins/clangtools/clangtidyclazyrunner.cpp
++++ b/src/plugins/clangtools/clangtidyclazyrunner.cpp
+@@ -86,12 +87,12 @@ QStringList ClangTidyClazyRunner::constructCommandLineArguments(const QStringLis
+ const QString clazyChecks = m_diagnosticConfig.clazyChecks();
+ if (!clazyChecks.isEmpty()) {
+ arguments << XclangArgs({"-add-plugin",
+- "clang-lazy",
+- "-plugin-arg-clang-lazy",
++ "clazy",
++ "-plugin-arg-clazy",
+ "enable-all-fixits",
+- "-plugin-arg-clang-lazy",
++ "-plugin-arg-clazy",
+ "no-autowrite-fixits",
+- "-plugin-arg-clang-lazy",
++ "-plugin-arg-clazy",
+ m_diagnosticConfig.clazyChecks()});
+ }
+
diff --git a/qtcreator-cmake-edit-fix.patch b/qtcreator-cmake-edit-fix.patch
deleted file mode 100644
index 40f59c80e28e..000000000000
--- a/qtcreator-cmake-edit-fix.patch
+++ /dev/null
@@ -1,34 +0,0 @@
-diff --git a/src/plugins/cmakeprojectmanager/cmakebuildsettingswidget.cpp b/src/plugins/cmakeprojectmanager/cmakebuildsettingswidget.cpp
-index 396bc00f68..5f0fad9260 100644
---- a/src/plugins/cmakeprojectmanager/cmakebuildsettingswidget.cpp
-+++ b/src/plugins/cmakeprojectmanager/cmakebuildsettingswidget.cpp
-@@ -171,6 +171,12 @@ CMakeBuildSettingsWidget::CMakeBuildSettingsWidget(CMakeBuildConfiguration *bc)
- m_configTextFilterModel->setFilterKeyColumn(-1);
- m_configTextFilterModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
-
-+ connect(m_configTextFilterModel, &QAbstractItemModel::layoutChanged, this, [this]() {
-+ QModelIndex selectedIdx = m_configView->currentIndex();
-+ if (selectedIdx.isValid())
-+ m_configView->scrollTo(selectedIdx);
-+ });
-+
- m_configView->setModel(m_configTextFilterModel);
- m_configView->setMinimumHeight(300);
- m_configView->setUniformRowHeights(true);
-@@ -307,9 +313,13 @@ CMakeBuildSettingsWidget::CMakeBuildSettingsWidget(CMakeBuildConfiguration *bc)
- value = QString::fromLatin1("OFF");
-
- m_configModel->appendConfiguration(tr("<UNSET>"), value, type);
-- QModelIndex idx;
-- idx = m_configView->model()->index(
-- m_configView->model()->rowCount(idx) - 1, 0);
-+ const Utils::TreeItem* item = m_configModel->findNonRootItem([&value, type](Utils::TreeItem* item) {
-+ ConfigModel::DataItem dataItem = ConfigModel::dataItemFromIndex(item->index());
-+ return dataItem.key == tr("<UNSET>") && dataItem.type == type && dataItem.value == value;
-+ });
-+ QModelIndex idx = m_configModel->indexForItem(item);
-+ idx = m_configTextFilterModel->mapFromSource(m_configFilterModel->mapFromSource(idx));
-+ m_configView->scrollTo(idx);
- m_configView->setCurrentIndex(idx);
- m_configView->edit(idx);
- });
diff --git a/qtcreator-cmake-fail-target-fix.patch b/qtcreator-cmake-fail-target-fix.patch
deleted file mode 100644
index a768fb9033e0..000000000000
--- a/qtcreator-cmake-fail-target-fix.patch
+++ /dev/null
@@ -1,29 +0,0 @@
-diff --git a/src/plugins/cmakeprojectmanager/cmakebuildstep.cpp b/src/plugins/cmakeprojectmanager/cmakebuildstep.cpp
-index 21556ce0fd..f319af05d4 100644
---- a/src/plugins/cmakeprojectmanager/cmakebuildstep.cpp
-+++ b/src/plugins/cmakeprojectmanager/cmakebuildstep.cpp
-@@ -115,8 +115,10 @@ CMakeRunConfiguration *CMakeBuildStep::targetsActiveRunConfiguration() const
- return qobject_cast<CMakeRunConfiguration *>(target()->activeRunConfiguration());
- }
-
--void CMakeBuildStep::handleBuildTargetChanges()
-+void CMakeBuildStep::handleBuildTargetChanges(bool success)
- {
-+ if (!success)
-+ return; // Do not change when parsing failed.
- if (isCurrentExecutableTarget(m_buildTarget))
- return; // Do not change just because a different set of build targets is there...
- if (!static_cast<CMakeProject *>(project())->buildTargetTitles().contains(m_buildTarget))
-diff --git a/src/plugins/cmakeprojectmanager/cmakebuildstep.h b/src/plugins/cmakeprojectmanager/cmakebuildstep.h
-index cfae9c9aab..91dab9b455 100644
---- a/src/plugins/cmakeprojectmanager/cmakebuildstep.h
-+++ b/src/plugins/cmakeprojectmanager/cmakebuildstep.h
-@@ -101,7 +101,7 @@ private:
- void runImpl(QFutureInterface<bool> &fi);
- void handleProjectWasParsed(QFutureInterface<bool> &fi, bool success);
-
-- void handleBuildTargetChanges();
-+ void handleBuildTargetChanges(bool success);
- CMakeRunConfiguration *targetsActiveRunConfiguration() const;
-
- QMetaObject::Connection m_runTrigger;
diff --git a/qtcreator-debugger-columns-fix.patch b/qtcreator-debugger-columns-fix.patch
deleted file mode 100644
index 4f4a632d7ea3..000000000000
--- a/qtcreator-debugger-columns-fix.patch
+++ /dev/null
@@ -1,343 +0,0 @@
-diff --git a/src/libs/utils/basetreeview.cpp b/src/libs/utils/basetreeview.cpp
-index bae4c16fef..3fc12130b7 100644
---- a/src/libs/utils/basetreeview.cpp
-+++ b/src/libs/utils/basetreeview.cpp
-@@ -55,6 +55,42 @@ public:
- m_settingsTimer.setSingleShot(true);
- connect(&m_settingsTimer, &QTimer::timeout,
- this, &BaseTreeViewPrivate::doSaveState);
-+ connect(q->header(), &QHeaderView::sectionResized, this, [this](int logicalIndex, int oldSize, int newSize) {
-+ if (m_processingSpans || m_spanColumn < 0)
-+ return;
-+
-+ QHeaderView *h = q->header();
-+ QTC_ASSERT(h, return);
-+
-+ // Last non-hidden column.
-+ int count = h->count();
-+ while (count > 0 && h->isSectionHidden(count - 1))
-+ --count;
-+
-+ if (count == 0)
-+ return;
-+
-+ int column = logicalIndex;
-+ if (oldSize < newSize)
-+ {
-+ // Protect against sizing past the next section.
-+ while (column + 1 < count && h->sectionSize(column + 1) == h->minimumSectionSize())
-+ ++column;
-+ }
-+
-+ if (logicalIndex >= m_spanColumn) {
-+ // Resize after the span column.
-+ column = column + 1;
-+ } else {
-+ // Resize the span column or before it.
-+ column = m_spanColumn;
-+ }
-+
-+ rebalanceColumns(column, false);
-+ });
-+ connect(q->header(), &QHeaderView::geometriesChanged, this, [this]() {
-+ rebalanceColumns();
-+ });
- }
-
- bool eventFilter(QObject *, QEvent *event) override
-@@ -197,6 +233,17 @@ public:
- }
- }
-
-+ void setSpanColumn(int column)
-+ {
-+ if (column == m_spanColumn)
-+ return;
-+
-+ m_spanColumn = column;
-+ if (m_spanColumn >= 0)
-+ q->header()->setStretchLastSection(false);
-+ rebalanceColumns();
-+ }
-+
- void toggleColumnWidth(int logicalIndex)
- {
- QHeaderView *h = q->header();
-@@ -211,11 +258,72 @@ public:
- int minSize = 10 * fm.width(QLatin1Char('x'));
- targetSize = qMax(minSize, headerSize);
- }
-+
-+ // Prevent rebalance as part of this resize.
-+ m_processingSpans = true;
- h->resizeSection(logicalIndex, targetSize);
-+ m_processingSpans = false;
-+
-+ // Now trigger a rebalance so it resizes the span column. (if set)
-+ rebalanceColumns();
-+
- m_userHandled.remove(logicalIndex); // Reset.
- saveState();
- }
-
-+ void rebalanceColumns()
-+ {
-+ rebalanceColumns(m_spanColumn, true);
-+ }
-+
-+ void rebalanceColumns(int column, bool allowResizePrevious)
-+ {
-+ if (m_spanColumn < 0 || column < 0 || m_processingSpans)
-+ return;
-+
-+ QHeaderView *h = q->header();
-+ QTC_ASSERT(h, return);
-+
-+ int count = h->count();
-+ if (column >= count)
-+ return;
-+
-+ // Start with the target column, and resize other columns as necessary.
-+ int totalSize = q->viewport()->width();
-+ if (tryRebalanceColumns(column, totalSize))
-+ return;
-+
-+ for (int i = allowResizePrevious ? 0 : column + 1; i < count; ++i) {
-+ if (i != column && tryRebalanceColumns(i, totalSize))
-+ return;
-+ }
-+ }
-+
-+ bool tryRebalanceColumns(int column, int totalSize)
-+ {
-+ QHeaderView *h = q->header();
-+
-+ int count = h->count();
-+ int otherColumnTotal = 0;
-+ for (int i = 0; i < count; ++i) {
-+ if (i != column)
-+ otherColumnTotal += h->sectionSize(i);
-+ }
-+
-+ if (otherColumnTotal < totalSize) {
-+ m_processingSpans = true;
-+ h->resizeSection(column, totalSize - otherColumnTotal);
-+ m_processingSpans = false;
-+ } else
-+ return false;
-+
-+ // Make sure this didn't go over the total size.
-+ int totalColumnSize = 0;
-+ for (int i = 0; i < count; ++i)
-+ totalColumnSize += h->sectionSize(i);
-+ return totalColumnSize == totalSize;
-+ }
-+
- public:
- BaseTreeView *q;
- QMap<int, int> m_userHandled; // column -> width, "not present" means "automatic"
-@@ -224,6 +332,8 @@ public:
- QString m_settingsKey;
- bool m_expectUserChanges = false;
- ProgressIndicator *m_progressIndicator = nullptr;
-+ int m_spanColumn = -1;
-+ bool m_processingSpans = false;
- };
-
- class BaseTreeViewDelegate : public QItemDelegate
-@@ -369,6 +479,12 @@ void BaseTreeView::mouseDoubleClickEvent(QMouseEvent *ev)
- TreeView::mouseDoubleClickEvent(ev);
- }
-
-+void BaseTreeView::resizeEvent(QResizeEvent *ev)
-+{
-+ TreeView::resizeEvent(ev);
-+ d->rebalanceColumns();
-+}
-+
- void BaseTreeView::showEvent(QShowEvent *ev)
- {
- emit aboutToShow();
-@@ -416,6 +532,21 @@ void BaseTreeView::resizeColumns()
- d->resizeColumns();
- }
-
-+int BaseTreeView::spanColumn() const
-+{
-+ return d->m_spanColumn;
-+}
-+
-+void BaseTreeView::setSpanColumn(int column)
-+{
-+ d->setSpanColumn(column);
-+}
-+
-+void BaseTreeView::refreshSpanColumn()
-+{
-+ d->rebalanceColumns();
-+}
-+
- void BaseTreeView::setSettings(QSettings *settings, const QByteArray &key)
- {
- QTC_ASSERT(!d->m_settings, qDebug() << "DUPLICATED setSettings" << key);
-diff --git a/src/libs/utils/basetreeview.h b/src/libs/utils/basetreeview.h
-index 923c69b042..36da658913 100644
---- a/src/libs/utils/basetreeview.h
-+++ b/src/libs/utils/basetreeview.h
-@@ -68,11 +68,19 @@ public:
- void dropEvent(QDropEvent *ev) override;
- void dragMoveEvent(QDragMoveEvent *ev) override;
- void mouseDoubleClickEvent(QMouseEvent *ev) override;
-+ void resizeEvent(QResizeEvent *event) override;
-
- void showProgressIndicator();
- void hideProgressIndicator();
- void resizeColumns();
-
-+ int spanColumn() const;
-+ void setSpanColumn(int column);
-+
-+ // In some situations this needs to be called when manually resizing columns when the span
-+ // column is set.
-+ void refreshSpanColumn();
-+
- signals:
- void aboutToShow();
-
-diff --git a/src/plugins/debugger/debuggerengine.cpp b/src/plugins/debugger/debuggerengine.cpp
-index 0925cb79e4..0e642e4740 100644
---- a/src/plugins/debugger/debuggerengine.cpp
-+++ b/src/plugins/debugger/debuggerengine.cpp
-@@ -647,7 +647,7 @@ void DebuggerEnginePrivate::setupViews()
- m_registerWindow->setObjectName(DOCKWIDGET_REGISTER);
- m_registerWindow->setWindowTitle(tr("Reg&isters"));
-
-- m_stackView = new BaseTreeView;
-+ m_stackView = new StackTreeView;
- m_stackView->setModel(m_stackHandler.model());
- m_stackView->setSettings(settings, "Debugger.StackView");
- m_stackView->setIconSize(QSize(10, 10));
-@@ -671,6 +671,7 @@ void DebuggerEnginePrivate::setupViews()
- m_threadsView->setSortingEnabled(true);
- m_threadsView->setSettings(settings, "Debugger.ThreadsView");
- m_threadsView->setIconSize(QSize(10, 10));
-+ m_threadsView->setSpanColumn(ThreadData::FunctionColumn);
- m_threadsWindow = addSearch(m_threadsView);
- m_threadsWindow->setObjectName(DOCKWIDGET_THREADS);
- m_threadsWindow->setWindowTitle(tr("&Threads"));
-@@ -716,6 +717,7 @@ void DebuggerEnginePrivate::setupViews()
- m_breakView->setIconSize(QSize(10, 10));
- m_breakView->setWindowIcon(Icons::BREAKPOINTS.icon());
- m_breakView->setSelectionMode(QAbstractItemView::ExtendedSelection);
-+ m_breakView->setSpanColumn(BreakpointFunctionColumn);
- connect(action(UseAddressInBreakpointsView), &QAction::toggled,
- this, [this](bool on) { m_breakView->setColumnHidden(BreakpointAddressColumn, !on); });
- m_breakView->setSettings(settings, "Debugger.BreakWindow");
-diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp
-index 3f7b01d2bd..042ea05804 100644
---- a/src/plugins/debugger/debuggerplugin.cpp
-+++ b/src/plugins/debugger/debuggerplugin.cpp
-@@ -1038,6 +1038,7 @@ bool DebuggerPluginPrivate::initialize(const QStringList &arguments,
- m_breakpointManagerView->setSettings(settings, "Debugger.BreakWindow");
- m_breakpointManagerView->setRootIsDecorated(true);
- m_breakpointManagerView->setModel(BreakpointManager::model());
-+ m_breakpointManagerView->setSpanColumn(BreakpointFunctionColumn);
- m_breakpointManagerWindow = addSearch(m_breakpointManagerView);
- m_breakpointManagerWindow->setWindowTitle(tr("Breakpoint Preset"));
- m_breakpointManagerWindow->setObjectName(DOCKWIDGET_BREAKPOINTMANAGER);
-diff --git a/src/plugins/debugger/stackwindow.cpp b/src/plugins/debugger/stackwindow.cpp
-index 83e6af2829..e25f6aa72b 100644
---- a/src/plugins/debugger/stackwindow.cpp
-+++ b/src/plugins/debugger/stackwindow.cpp
-@@ -32,33 +32,56 @@
- #include <utils/savedaction.h>
-
- #include <QAction>
-+#include <QHeaderView>
-
- namespace Debugger {
- namespace Internal {
-
--StackTreeView::StackTreeView()
-+StackTreeView::StackTreeView(QWidget *parent)
-+ : BaseTreeView(parent)
- {
-- setWindowTitle(tr("Stack"));
--
- connect(action(UseAddressInStackView), &QAction::toggled,
- this, &StackTreeView::showAddressColumn);
-+ setSpanColumn(StackFunctionNameColumn);
- showAddressColumn(false);
- }
-
-+void StackTreeView::setModel(QAbstractItemModel *model)
-+{
-+ BaseTreeView::setModel(model);
-+ connect(static_cast<StackHandler*>(model), &StackHandler::stackChanged,
-+ this, [this]() {
-+ if (!m_contentsAdjusted)
-+ adjustForContents();
-+ });
-+
-+ // Resize for the current contents if any are available.
-+ showAddressColumn(action(UseAddressInStackView)->isChecked());
-+}
-+
- void StackTreeView::showAddressColumn(bool on)
- {
- setColumnHidden(StackAddressColumn, !on);
-- resizeColumnToContents(StackLevelColumn);
-- resizeColumnToContents(StackLineNumberColumn);
-- resizeColumnToContents(StackAddressColumn);
-+ adjustForContents(true);
- }
-
--void StackTreeView::setModel(QAbstractItemModel *model)
-+void StackTreeView::adjustForContents(bool refreshSpan)
- {
-- BaseTreeView::setModel(model);
-+ // Skip resizing if no contents. This will be called again once contents are available.
-+ if (!model() || model()->rowCount() == 0) {
-+ if (refreshSpan)
-+ refreshSpanColumn();
-+ return;
-+ }
-+
-+ // Resize without attempting to fix up the columns.
-+ setSpanColumn(-1);
- resizeColumnToContents(StackLevelColumn);
-+ resizeColumnToContents(StackFileNameColumn);
- resizeColumnToContents(StackLineNumberColumn);
-- showAddressColumn(action(UseAddressInStackView)->isChecked());
-+ resizeColumnToContents(StackAddressColumn);
-+ setSpanColumn(StackFunctionNameColumn);
-+ m_contentsAdjusted = true;
- }
-
- } // namespace Internal
-diff --git a/src/plugins/debugger/stackwindow.h b/src/plugins/debugger/stackwindow.h
-index 5439ead73f..79f2974e82 100644
---- a/src/plugins/debugger/stackwindow.h
-+++ b/src/plugins/debugger/stackwindow.h
-@@ -34,17 +34,16 @@ namespace Internal {
-
- class StackTreeView : public Utils::BaseTreeView
- {
-- Q_DECLARE_TR_FUNCTIONS(Debugger::Internal::StackTreeView)
--
- public:
-- StackTreeView();
-+ explicit StackTreeView(QWidget *parent = nullptr);
-
- private:
- void setModel(QAbstractItemModel *model) override;
-
- void showAddressColumn(bool on);
-- void reloadFullStack();
-- void copyContentsToClipboard();
-+ void adjustForContents(bool refreshSpan = false);
-+
-+ bool m_contentsAdjusted = false;
- };
-
- } // namespace Internal
diff --git a/qtcreator-debugger-layout.patch b/qtcreator-debugger-layout.patch
new file mode 100644
index 000000000000..a1823176162f
--- /dev/null
+++ b/qtcreator-debugger-layout.patch
@@ -0,0 +1,1715 @@
+diff --git a/src/libs/utils/fancymainwindow.cpp b/src/libs/utils/fancymainwindow.cpp
+index 9a5c84894c..de73c6edaa 100644
+--- a/src/libs/utils/fancymainwindow.cpp
++++ b/src/libs/utils/fancymainwindow.cpp
+@@ -523,21 +523,6 @@ bool FancyMainWindow::autoHideTitleBars() const
+ return d->m_autoHideTitleBars.isChecked();
+ }
+
+-void FancyMainWindow::setAutoHideTitleBars(bool on)
+-{
+- d->m_autoHideTitleBars.setChecked(on);
+-}
+-
+-bool FancyMainWindow::isCentralWidgetShown() const
+-{
+- return d->m_showCentralWidget.isChecked();
+-}
+-
+-void FancyMainWindow::showCentralWidget(bool on)
+-{
+- d->m_showCentralWidget.setChecked(on);
+-}
+-
+ void FancyMainWindow::addDockActionsToMenu(QMenu *menu)
+ {
+ QList<QAction *> actions;
+diff --git a/src/libs/utils/fancymainwindow.h b/src/libs/utils/fancymainwindow.h
+index 4424b1c8bb..623ef42408 100644
+--- a/src/libs/utils/fancymainwindow.h
++++ b/src/libs/utils/fancymainwindow.h
+@@ -66,10 +66,6 @@ public:
+ void addDockActionsToMenu(QMenu *menu);
+
+ bool autoHideTitleBars() const;
+- void setAutoHideTitleBars(bool on);
+-
+- bool isCentralWidgetShown() const;
+- void showCentralWidget(bool on);
+
+ signals:
+ // Emitted by resetLayoutAction(). Connect to a slot
+diff --git a/src/plugins/debugger/debuggerengine.cpp b/src/plugins/debugger/debuggerengine.cpp
+index b86bb1088e..5f89c07875 100644
+--- a/src/plugins/debugger/debuggerengine.cpp
++++ b/src/plugins/debugger/debuggerengine.cpp
+@@ -61,7 +61,6 @@
+ #include <coreplugin/icore.h>
+ #include <coreplugin/idocument.h>
+ #include <coreplugin/messagebox.h>
+-#include <coreplugin/modemanager.h>
+ #include <coreplugin/progressmanager/progressmanager.h>
+ #include <coreplugin/progressmanager/futureprogress.h>
+
+@@ -281,16 +280,12 @@ public:
+ m_disassemblerAgent(engine),
+ m_toolTipManager(engine)
+ {
+- m_debuggerName = DebuggerEngine::tr("Debugger");
+-
+ m_logWindow = new LogWindow(m_engine); // Needed before start()
+- m_logWindow->setObjectName("Debugger.Dock.Output");
++ m_logWindow->setObjectName(DOCKWIDGET_OUTPUT);
++ m_debuggerName = DebuggerEngine::tr("Debugger");
+
+- connect(action(EnableReverseDebugging), &SavedAction::valueChanged, this, [this] {
+- updateState();
+- if (m_companionEngine)
+- m_companionEngine->d->updateState();
+- });
++ connect(action(EnableReverseDebugging), &SavedAction::valueChanged,
++ this, [this] { updateState(true); });
+ static int contextCount = 0;
+ m_context = Context(Id("Debugger.Engine.").withSuffix(++contextCount));
+
+@@ -375,15 +370,17 @@ public:
+ if (!m_perspective)
+ return;
+
+- Perspective *perspective = m_perspective;
++ delete m_perspective;
+ m_perspective = nullptr;
+
+ EngineManager::unregisterEngine(m_engine);
+
+- // This triggers activity in the EngineManager which
+- // recognizes the rampdown by the m_perpective == nullptr above.
+- perspective->destroy();
+- delete perspective;
++ // Give up ownership on claimed breakpoints.
++ m_breakHandler.releaseAllBreakpoints();
++ m_toolTipManager.deregisterEngine();
++ m_memoryAgents.handleDebuggerFinished();
++
++ setBusyCursor(false);
+ }
+
+ void updateReturnViewHeader(int section, int, int newSize)
+@@ -449,14 +446,14 @@ public:
+ void setInitialActionStates();
+ void setBusyCursor(bool on);
+ void cleanupViews();
+- void updateState();
++ void updateState(bool alsoUpdateCompanion);
+ void updateReverseActions();
+
+ DebuggerEngine *m_engine = nullptr; // Not owned.
+ QString m_runId;
+ QPointer<RunConfiguration> m_runConfiguration; // Not owned.
+ QString m_debuggerName;
+- QPointer<Perspective> m_perspective;
++ Perspective *m_perspective = nullptr;
+ DebuggerRunParameters m_runParameters;
+ IDevice::ConstPtr m_device;
+
+@@ -554,17 +551,16 @@ public:
+ void DebuggerEnginePrivate::setupViews()
+ {
+ const DebuggerRunParameters &rp = m_runParameters;
+- const QString engineId = EngineManager::registerEngine(m_engine);
+
+ QTC_CHECK(!m_perspective);
+
+- const QString perspectiveId = "Debugger.Perspective." + m_runId + '.' + m_debuggerName;
+- const QString settingsId = "Debugger.Perspective." + m_debuggerName;
+-
+- m_perspective = new Perspective(perspectiveId,
++ m_perspective = new Perspective("Debugger.Perspective." + m_runId + '.' + m_debuggerName,
+ m_engine->displayName(),
+ Debugger::Constants::PRESET_PERSPECTIVE_ID,
+- settingsId);
++ m_debuggerName);
++ m_perspective->setShouldPersistChecker([this] {
++ return EngineManager::isLastOf(m_debuggerName);
++ });
+
+ m_progress.setProgressRange(0, 1000);
+ FutureProgress *fp = ProgressManager::addTask(m_progress.future(),
+@@ -632,7 +628,7 @@ void DebuggerEnginePrivate::setupViews()
+ m_engine, &DebuggerEngine::reloadModules,
+ Qt::QueuedConnection);
+ m_modulesWindow = addSearch(m_modulesView);
+- m_modulesWindow->setObjectName("Debugger.Dock.Modules." + engineId);
++ m_modulesWindow->setObjectName(DOCKWIDGET_MODULES);
+ m_modulesWindow->setWindowTitle(tr("&Modules"));
+
+ m_registerView = new BaseTreeView;
+@@ -643,7 +639,7 @@ void DebuggerEnginePrivate::setupViews()
+ m_engine, &DebuggerEngine::reloadRegisters,
+ Qt::QueuedConnection);
+ m_registerWindow = addSearch(m_registerView);
+- m_registerWindow->setObjectName("Debugger.Dock.Register." + engineId);
++ m_registerWindow->setObjectName(DOCKWIDGET_REGISTER);
+ m_registerWindow->setWindowTitle(tr("Reg&isters"));
+
+ m_stackView = new StackTreeView;
+@@ -651,7 +647,7 @@ void DebuggerEnginePrivate::setupViews()
+ m_stackView->setSettings(settings, "Debugger.StackView");
+ m_stackView->setIconSize(QSize(10, 10));
+ m_stackWindow = addSearch(m_stackView);
+- m_stackWindow->setObjectName("Debugger.Dock.Stack." + engineId);
++ m_stackWindow->setObjectName(DOCKWIDGET_STACK);
+ m_stackWindow->setWindowTitle(tr("&Stack"));
+
+ m_sourceFilesView = new BaseTreeView;
+@@ -662,7 +658,7 @@ void DebuggerEnginePrivate::setupViews()
+ m_engine, &DebuggerEngine::reloadSourceFiles,
+ Qt::QueuedConnection);
+ m_sourceFilesWindow = addSearch(m_sourceFilesView);
+- m_sourceFilesWindow->setObjectName("Debugger.Dock.SourceFiles." + engineId);
++ m_sourceFilesWindow->setObjectName(DOCKWIDGET_SOURCE_FILES);
+ m_sourceFilesWindow->setWindowTitle(tr("Source Files"));
+
+ m_threadsView = new BaseTreeView;
+@@ -672,7 +668,7 @@ void DebuggerEnginePrivate::setupViews()
+ m_threadsView->setIconSize(QSize(10, 10));
+ m_threadsView->setSpanColumn(ThreadData::FunctionColumn);
+ m_threadsWindow = addSearch(m_threadsView);
+- m_threadsWindow->setObjectName("Debugger.Dock.Threads." + engineId);
++ m_threadsWindow->setObjectName(DOCKWIDGET_THREADS);
+ m_threadsWindow->setWindowTitle(tr("&Threads"));
+
+ m_returnView = new WatchTreeView{ReturnType};
+@@ -686,26 +682,26 @@ void DebuggerEnginePrivate::setupViews()
+ m_localsView->setModel(m_watchHandler.model());
+ m_localsView->setSettings(settings, "Debugger.LocalsView");
+ m_localsWindow = addSearch(m_localsView);
+- m_localsWindow->setObjectName("Debugger.Dock.Locals." + engineId);
++ m_localsWindow->setObjectName("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("Debugger.Dock.Inspector." + engineId);
++ m_inspectorWindow->setObjectName("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("Debugger.Dock.Watchers." + engineId);
++ m_watchersWindow->setObjectName("CppDebugWatchers");
+ m_watchersWindow->setWindowTitle(tr("&Expressions"));
+
+ m_localsAndInspectorWindow = new LocalsAndInspectorWindow(
+ m_localsWindow, m_inspectorWindow, m_returnWindow);
+- m_localsAndInspectorWindow->setObjectName("Debugger.Dock.LocalsAndInspector." + engineId);
++ m_localsAndInspectorWindow->setObjectName(DOCKWIDGET_LOCALS_AND_INSPECTOR);
+ m_localsAndInspectorWindow->setWindowTitle(m_localsWindow->windowTitle());
+
+ // Locals
+@@ -723,7 +719,7 @@ void DebuggerEnginePrivate::setupViews()
+ m_breakView->setModel(m_breakHandler.model());
+ m_breakView->setRootIsDecorated(true);
+ m_breakWindow = addSearch(m_breakView);
+- m_breakWindow->setObjectName("Debugger.Dock.Break." + engineId);
++ m_breakWindow->setObjectName(DOCKWIDGET_BREAK);
+ m_breakWindow->setWindowTitle(tr("&Breakpoints"));
+
+ m_perspective->useSubPerspectiveSwitcher(EngineManager::engineChooser());
+@@ -850,6 +846,7 @@ void DebuggerEnginePrivate::setupViews()
+ DebuggerEngine::DebuggerEngine()
+ : d(new DebuggerEnginePrivate(this))
+ {
++ updateState(false);
+ }
+
+ DebuggerEngine::~DebuggerEngine()
+@@ -1023,6 +1020,7 @@ void DebuggerEngine::setRunTool(DebuggerRunTool *runTool)
+
+ void DebuggerEngine::start()
+ {
++ EngineManager::registerEngine(this);
+ d->m_watchHandler.resetWatchers();
+ d->setInitialActionStates();
+ setState(EngineSetupRequested);
+@@ -1118,7 +1116,7 @@ void DebuggerEngine::abortDebugger()
+
+ void DebuggerEngine::updateUi(bool isCurrentEngine)
+ {
+- updateState();
++ updateState(false);
+ if (isCurrentEngine) {
+ gotoCurrentLocation();
+ } else {
+@@ -1321,7 +1319,7 @@ void DebuggerEngine::notifyInferiorSpontaneousStop()
+ {
+ showMessage("NOTE: INFERIOR SPONTANEOUS STOP");
+ QTC_ASSERT(state() == InferiorRunOk, qDebug() << this << state());
+- d->m_perspective->select();
++ EngineManager::activateEngine(this);
+ showMessage(tr("Stopped."), StatusBar);
+ setState(InferiorStopOk);
+ if (boolSetting(RaiseOnInterrupt))
+@@ -1388,12 +1386,10 @@ void DebuggerEnginePrivate::setInitialActionStates()
+ m_threadLabel->setEnabled(false);
+ }
+
+-void DebuggerEnginePrivate::updateState()
++void DebuggerEnginePrivate::updateState(bool alsoUpdateCompanion)
+ {
+- // Can happen in mixed debugging.
+- if (!m_threadLabel)
++ if (!m_perspective)
+ return;
+- QTC_ASSERT(m_threadLabel, return);
+
+ const DebuggerState state = m_state;
+ const bool companionPreventsAction = m_engine->companionPreventsActions();
+@@ -1403,7 +1399,7 @@ void DebuggerEnginePrivate::updateState()
+ // visible, possibly disabled.
+ if (state == DebuggerNotReady) {
+ // Happens when companion starts, otherwise this should not happen.
+- //QTC_CHECK(m_companionEngine);
++ QTC_CHECK(m_companionEngine);
+ m_interruptAction.setVisible(true);
+ m_interruptAction.setEnabled(false);
+ m_continueAction.setVisible(false);
+@@ -1533,6 +1529,9 @@ void DebuggerEnginePrivate::updateState()
+ || state == DebuggerFinished
+ || state == InferiorUnrunnable;
+ setBusyCursor(!notbusy);
++
++ if (alsoUpdateCompanion && m_companionEngine)
++ m_companionEngine->updateState(false);
+ }
+
+ void DebuggerEnginePrivate::updateReverseActions()
+@@ -1691,9 +1690,9 @@ void DebuggerEngine::notifyInferiorExited()
+ d->doShutdownEngine();
+ }
+
+-void DebuggerEngine::updateState()
++void DebuggerEngine::updateState(bool alsoUpdateCompanion)
+ {
+- d->updateState();
++ d->updateState(alsoUpdateCompanion);
+ }
+
+ WatchTreeView *DebuggerEngine::inspectorView()
+@@ -1794,28 +1793,17 @@ void DebuggerEngine::setState(DebuggerState state, bool forced)
+ if (!forced && !isAllowedTransition(oldState, state))
+ qDebug() << "*** UNEXPECTED STATE TRANSITION: " << this << msg;
+
+- if (state == EngineRunRequested) {
++ if (state == EngineRunRequested)
+ emit engineStarted();
+- d->m_perspective->select();
+- }
+
+ showMessage(msg, LogDebug);
+
+- d->updateState();
+- if (d->m_companionEngine)
+- d->m_companionEngine->d->updateState();
++ d->updateState(true);
+
+ if (oldState != d->m_state)
+ emit EngineManager::instance()->engineStateChanged(this);
+
+ if (state == DebuggerFinished) {
+- d->setBusyCursor(false);
+-
+- // Give up ownership on claimed breakpoints.
+- d->m_breakHandler.releaseAllBreakpoints();
+- d->m_toolTipManager.deregisterEngine();
+- d->m_memoryAgents.handleDebuggerFinished();
+-
+ d->destroyPerspective();
+ emit engineFinished();
+ }
+diff --git a/src/plugins/debugger/debuggerengine.h b/src/plugins/debugger/debuggerengine.h
+index 736d2b3c03..12e4356ce0 100644
+--- a/src/plugins/debugger/debuggerengine.h
++++ b/src/plugins/debugger/debuggerengine.h
+@@ -416,7 +416,7 @@ protected:
+ void notifyInferiorStopFailed();
+
+ public:
+- void updateState();
++ void updateState(bool alsoUpdateCompanion);
+ QString formatStartParameters() const;
+ WatchTreeView *inspectorView();
+ void updateLocalsWindow(bool showReturn);
+diff --git a/src/plugins/debugger/debuggerinternalconstants.h b/src/plugins/debugger/debuggerinternalconstants.h
+index 8f6599b653..cb9591e8ad 100644
+--- a/src/plugins/debugger/debuggerinternalconstants.h
++++ b/src/plugins/debugger/debuggerinternalconstants.h
+@@ -28,6 +28,24 @@
+ #include <QtGlobal>
+
+ namespace Debugger {
++namespace Internal {
++
++// DebuggerMainWindow dock widget names
++const char DOCKWIDGET_BREAKPOINTMANAGER[] = "Debugger.Docks.BreakpointManager";
++const char DOCKWIDGET_ENGINEMANAGER[] = "Debugger.Docks.Snapshots";
++const char DOCKWIDGET_GLOBALLOG[] = "Debugger.Docks.GlobalLog";
++
++const char DOCKWIDGET_BREAK[] = "Debugger.Docks.Break";
++const char DOCKWIDGET_MODULES[] = "Debugger.Docks.Modules";
++const char DOCKWIDGET_REGISTER[] = "Debugger.Docks.Register";
++const char DOCKWIDGET_OUTPUT[] = "Debugger.Docks.Output";
++const char DOCKWIDGET_STACK[] = "Debugger.Docks.Stack";
++const char DOCKWIDGET_SOURCE_FILES[] = "Debugger.Docks.SourceFiles";
++const char DOCKWIDGET_THREADS[] = "Debugger.Docks.Threads";
++const char DOCKWIDGET_LOCALS_AND_INSPECTOR[] = "Debugger.Docks.LocalsAndInspector";
++
++} // namespace Internal
++
+ namespace Constants {
+
+ const char DEBUGGER_COMMON_SETTINGS_ID[] = "A.Debugger.General";
+diff --git a/src/plugins/debugger/debuggermainwindow.cpp b/src/plugins/debugger/debuggermainwindow.cpp
+index 598344bb25..7d4175fc95 100644
+--- a/src/plugins/debugger/debuggermainwindow.cpp
++++ b/src/plugins/debugger/debuggermainwindow.cpp
+@@ -49,10 +49,9 @@
+
+ #include <QAction>
+ #include <QComboBox>
+-#include <QContextMenuEvent>
++#include <QDebug>
+ #include <QDockWidget>
+ #include <QHBoxLayout>
+-#include <QLoggingCategory>
+ #include <QMenu>
+ #include <QScrollArea>
+ #include <QStackedWidget>
+@@ -63,57 +62,37 @@
+ using namespace Debugger;
+ using namespace Core;
+
+-Q_LOGGING_CATEGORY(perspectivesLog, "qtc.utils.perspectives", QtWarningMsg)
+-
+ namespace Utils {
+
+-const int SettingsVersion = 3;
+-
+ const char LAST_PERSPECTIVE_KEY[] = "LastPerspective";
+-const char MAINWINDOW_KEY[] = "Debugger.MainWindow";
+-const char AUTOHIDE_TITLEBARS_KEY[] = "AutoHideTitleBars";
+-const char SHOW_CENTRALWIDGET_KEY[] = "ShowCentralWidget";
+-const char STATE_KEY[] = "State";
+-const char CHANGED_DOCK_KEY[] = "ChangedDocks";
++const char OWNED_BY_PERSPECTIVE[] = "OwnedByPerspective";
+
+ static DebuggerMainWindow *theMainWindow = nullptr;
+
+ class DockOperation
+ {
+ public:
+- void setupLayout();
+- QString name() const { QTC_ASSERT(widget, return QString()); return widget->objectName(); }
+-
+- Core::Id commandId;
+ QPointer<QWidget> widget;
+- QPointer<QDockWidget> dock;
+- QPointer<QWidget> anchorWidget;
++ QString anchorDockId;
+ Perspective::OperationType operationType = Perspective::Raise;
+ bool visibleByDefault = true;
+- bool visibleByUser = true;
+ Qt::DockWidgetArea area = Qt::BottomDockWidgetArea;
+ };
+
+ class PerspectivePrivate
+ {
+ public:
+- void showInnerToolBar();
+- void hideInnerToolBar();
++ void showToolBar();
++ void hideToolBar();
+ void restoreLayout();
+ void saveLayout();
+- void resetPerspective();
+- void populatePerspective();
+- void depopulatePerspective();
+- void saveAsLastUsedPerspective();
+- Context context() const;
+-
+ QString settingsId() const;
+ QToolButton *setupToolButton(QAction *action);
+
+ QString m_id;
+ QString m_name;
+ QString m_parentPerspectiveId;
+- QString m_settingsId;
++ QString m_subPerspectiveType;
+ QVector<DockOperation> m_dockOperations;
+ QPointer<QWidget> m_centralWidget;
+ Perspective::Callback m_aboutToActivateCallback;
+@@ -121,6 +100,8 @@ public:
+ QHBoxLayout *m_innerToolBarLayout = nullptr;
+ QPointer<QWidget> m_switcher;
+ QString m_lastActiveSubPerspectiveId;
++ QHash<QString, QVariant> m_nonPersistenSettings;
++ Perspective::ShouldPersistChecker m_shouldPersistChecker;
+ };
+
+ class DebuggerMainWindowPrivate : public QObject
+@@ -137,30 +118,20 @@ public:
+ void registerPerspective(Perspective *perspective);
+ void resetCurrentPerspective();
+ int indexInChooser(Perspective *perspective) const;
++ void fixupLayoutIfNeeded();
+ void updatePerspectiveChooserWidth();
+
+- void cleanDocks();
+- void setCentralWidget(QWidget *widget);
+-
+- QDockWidget *dockForWidget(QWidget *widget) const;
+-
+- void setCurrentPerspective(Perspective *perspective)
+- {
+- m_currentPerspective = perspective;
+- }
+-
+ DebuggerMainWindow *q = nullptr;
+- QPointer<Perspective> m_currentPerspective = nullptr;
++ Perspective *m_currentPerspective = nullptr;
+ QComboBox *m_perspectiveChooser = nullptr;
+ QStackedWidget *m_centralWidgetStack = nullptr;
+ QHBoxLayout *m_subPerspectiveSwitcherLayout = nullptr;
+ QHBoxLayout *m_innerToolsLayout = nullptr;
+- QPointer<QWidget> m_editorPlaceHolder;
++ QWidget *m_editorPlaceHolder = nullptr;
+ Utils::StatusLabel *m_statusLabel = nullptr;
+ QDockWidget *m_toolBarDock = nullptr;
+
+- QList<QPointer<Perspective>> m_perspectives;
+- QSet<QString> m_persistentChangedDocks;
++ QList<Perspective *> m_perspectives;
+ };
+
+ DebuggerMainWindowPrivate::DebuggerMainWindowPrivate(DebuggerMainWindow *parent)
+@@ -240,9 +211,10 @@ DebuggerMainWindowPrivate::DebuggerMainWindowPrivate(DebuggerMainWindow *parent)
+ m_toolBarDock = dock;
+ q->addDockWidget(Qt::BottomDockWidgetArea, m_toolBarDock);
+
+- connect(viewButton, &QAbstractButton::clicked, this, [this, viewButton] {
+- ActionContainer *viewsMenu = ActionManager::actionContainer(Core::Constants::M_WINDOW_VIEWS);
+- viewsMenu->menu()->exec(viewButton->mapToGlobal(QPoint()));
++ connect(viewButton, &QAbstractButton::clicked, [this, viewButton] {
++ QMenu menu;
++ q->addDockActionsToMenu(&menu);
++ menu.exec(viewButton->mapToGlobal(QPoint()));
+ });
+
+ connect(closeButton, &QAbstractButton::clicked, [] {
+@@ -284,19 +256,6 @@ DebuggerMainWindow::DebuggerMainWindow()
+ "Debugger.Views.ResetSimple", debugcontext);
+ cmd->setAttribute(Command::CA_Hide);
+ viewsMenu->addAction(cmd, Core::Constants::G_DEFAULT_THREE);
+-
+- connect(ICore::instance(), &ICore::saveSettingsRequested, this, [this] {
+- // There's one saveSettings triggered after plugin loading intentionally.
+- // We do not want to save anything at that time.
+- static bool firstOne = true;
+- if (firstOne) {
+- qCDebug(perspectivesLog) << "FIRST SAVE SETTINGS REQUEST IGNORED";
+- firstOne = false;
+- } else {
+- qCDebug(perspectivesLog) << "SAVING SETTINGS";
+- savePersistentSettings();
+- }
+- });
+ }
+
+ DebuggerMainWindow::~DebuggerMainWindow()
+@@ -304,12 +263,6 @@ DebuggerMainWindow::~DebuggerMainWindow()
+ delete d;
+ }
+
+-void DebuggerMainWindow::contextMenuEvent(QContextMenuEvent *ev)
+-{
+- ActionContainer *viewsMenu = ActionManager::actionContainer(Core::Constants::M_WINDOW_VIEWS);
+- viewsMenu->menu()->exec(ev->globalPos());
+-}
+-
+ void DebuggerMainWindow::ensureMainWindowExists()
+ {
+ if (!theMainWindow)
+@@ -318,8 +271,6 @@ void DebuggerMainWindow::ensureMainWindowExists()
+
+ void DebuggerMainWindow::doShutdown()
+ {
+- QTC_ASSERT(theMainWindow, return);
+-
+ delete theMainWindow;
+ theMainWindow = nullptr;
+ }
+@@ -335,12 +286,9 @@ void DebuggerMainWindowPrivate::registerPerspective(Perspective *perspective)
+
+ void DebuggerMainWindowPrivate::destroyPerspective(Perspective *perspective)
+ {
+- qCDebug(perspectivesLog) << "ABOUT TO DESTROY PERSPECTIVE" << perspective->id();
+-
+- const bool wasCurrent = perspective == m_currentPerspective;
+- if (wasCurrent) {
+- qCDebug(perspectivesLog) << "RAMPING IT DOWN FIRST AS IT WAS CURRENT" << perspective->id();
+- perspective->rampDownAsCurrent();
++ if (perspective == m_currentPerspective) {
++ depopulateCurrentPerspective();
++ m_currentPerspective = nullptr;
+ }
+
+ m_perspectives.removeAll(perspective);
+@@ -350,31 +298,6 @@ void DebuggerMainWindowPrivate::destroyPerspective(Perspective *perspective)
+ const int idx = indexInChooser(perspective);
+ if (idx != -1)
+ m_perspectiveChooser->removeItem(idx);
+-
+- for (DockOperation &op : perspective->d->m_dockOperations) {
+- if (op.commandId.isValid())
+- ActionManager::unregisterAction(op.dock->toggleViewAction(), op.commandId);
+- if (op.dock) {
+- theMainWindow->removeDockWidget(op.dock);
+- op.widget->setParent(nullptr); // Prevent deletion
+- op.dock->setParent(nullptr);
+- delete op.dock;
+- op.dock = nullptr;
+- }
+- }
+-
+- if (wasCurrent) {
+- if (Perspective *parent = Perspective::findPerspective(perspective->d->m_parentPerspectiveId)) {
+- qCDebug(perspectivesLog) << "RAMPING UP PARENT PERSPECTIVE" << parent->id();
+- parent->rampUpAsCurrent();
+- } else {
+- qCDebug(perspectivesLog) << "RAMPED DOWN WAS ACTION, BUT NO PARENT AVAILABLE. TAKE FIRST BEST";
+- if (QTC_GUARD(!m_perspectives.isEmpty()))
+- m_perspectives.first()->rampUpAsCurrent();
+- }
+- }
+-
+- qCDebug(perspectivesLog) << "DESTROYED PERSPECTIVE" << perspective->id();
+ }
+
+ void DebuggerMainWindow::showStatusMessage(const QString &message, int timeoutMS)
+@@ -386,124 +309,34 @@ void DebuggerMainWindow::showStatusMessage(const QString &message, int timeoutMS
+ void DebuggerMainWindow::enterDebugMode()
+ {
+ theMainWindow->setDockActionsVisible(true);
+- theMainWindow->restorePersistentSettings();
+- QTC_CHECK(theMainWindow->d->m_currentPerspective == nullptr);
+-
+- QSettings *settings = ICore::settings();
+- const QString lastPerspectiveId = settings->value(LAST_PERSPECTIVE_KEY).toString();
+- Perspective *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();
+-
++ Perspective *perspective = theMainWindow->d->m_currentPerspective;
++ if (!perspective) {
++ const QSettings *settings = ICore::settings();
++ const QString lastPerspectiveId = settings->value(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);
+-
+- if (auto sub = Perspective::findPerspective(perspective->d->m_lastActiveSubPerspectiveId)) {
+- qCDebug(perspectivesLog) << "SWITCHING TO SUBPERSPECTIVE" << sub->d->m_id;
+- perspective = sub;
+- }
+-
+- perspective->rampUpAsCurrent();
++ perspective->select();
+ }
+
+ void DebuggerMainWindow::leaveDebugMode()
+ {
+- theMainWindow->savePersistentSettings();
+-
+- if (theMainWindow->d->m_currentPerspective)
+- theMainWindow->d->m_currentPerspective->rampDownAsCurrent();
+- QTC_CHECK(theMainWindow->d->m_currentPerspective == nullptr);
++ if (Perspective *perspective = theMainWindow->d->m_currentPerspective)
++ perspective->d->saveLayout();
+
+ theMainWindow->setDockActionsVisible(false);
+
+ // Hide dock widgets manually in case they are floating.
+ for (QDockWidget *dockWidget : theMainWindow->dockWidgets()) {
+ if (dockWidget->isFloating())
+- dockWidget->setVisible(false);
+- }
+-}
+-
+-void DebuggerMainWindow::restorePersistentSettings()
+-{
+- qCDebug(perspectivesLog) << "RESTORE PERSISTENT";
+- QSettings *settings = ICore::settings();
+- settings->beginGroup(MAINWINDOW_KEY);
+- const bool res = theMainWindow->restoreState(settings->value(STATE_KEY).toByteArray(),
+- SettingsVersion);
+- if (!res)
+- qCDebug(perspectivesLog) << "NO READABLE PERSISTENT SETTINGS FOUND, ASSUMING NEW CLEAN SETTINGS";
+-
+- theMainWindow->setAutoHideTitleBars(settings->value(AUTOHIDE_TITLEBARS_KEY, true).toBool());
+- theMainWindow->showCentralWidget(settings->value(SHOW_CENTRALWIDGET_KEY, true).toBool());
+- theMainWindow->d->m_persistentChangedDocks
+- = QSet<QString>::fromList(settings->value(CHANGED_DOCK_KEY).toStringList());
+- settings->endGroup();
+-
+- qCDebug(perspectivesLog) << "LOADED DOCKS:" << theMainWindow->d->m_persistentChangedDocks;
+-
+- QTC_ASSERT(theMainWindow, return);
+- QTC_ASSERT(theMainWindow->d, return);
+- for (Perspective *perspective : theMainWindow->d->m_perspectives) {
+- QTC_ASSERT(perspective, continue);
+- qCDebug(perspectivesLog) << "RESTORING PERSPECTIVE" << perspective->d->m_id;
+- for (DockOperation &op : perspective->d->m_dockOperations) {
+- if (op.operationType != Perspective::Raise) {
+- QTC_ASSERT(op.dock, continue);
+- QTC_ASSERT(op.widget, continue);
+- if (theMainWindow->d->m_persistentChangedDocks.contains(op.name())) {
+- qCDebug(perspectivesLog) << "DOCK " << op.name() << "*** UNUSUAL";
+- op.visibleByUser = !op.visibleByDefault;
+- } else {
+- qCDebug(perspectivesLog) << "DOCK " << op.name() << "NORMAL";
+- QTC_CHECK(op.visibleByUser == op.visibleByDefault);
+- }
+- }
+- }
+- }
+-}
+-
+-Perspective *DebuggerMainWindow::currentPerspective()
+-{
+- return theMainWindow->d->m_currentPerspective;
+-}
+-
+-void DebuggerMainWindow::savePersistentSettings()
+-{
+- // The current one might have active, non saved changes.
+- if (Perspective *perspective = theMainWindow->d->m_currentPerspective)
+- perspective->d->saveLayout();
+-
+- qCDebug(perspectivesLog) << "SAVE PERSISTENT";
+-
+- QSet<QString> changedDocks = theMainWindow->d->m_persistentChangedDocks;
+- for (Perspective *perspective : theMainWindow->d->m_perspectives) {
+- QTC_ASSERT(perspective, continue);
+- qCDebug(perspectivesLog) << "SAVE PERSPECTIVE" << perspective->d->m_id;
+- for (const DockOperation &op : perspective->d->m_dockOperations) {
+- if (op.operationType != Perspective::Raise) {
+- QTC_ASSERT(op.dock, continue);
+- QTC_ASSERT(op.widget, continue);
+- qCDebug(perspectivesLog) << "DOCK " << op.name() << "ACTIVE: " << op.visibleByUser;
+- if (op.visibleByUser != op.visibleByDefault)
+- changedDocks.insert(op.name());
+- else
+- changedDocks.remove(op.name());
+- }
+- }
++ dockWidget->hide();
+ }
+- theMainWindow->d->m_persistentChangedDocks = changedDocks;
+- qCDebug(perspectivesLog) << "CHANGED DOCKS:" << changedDocks;
+-
+- QSettings *settings = ICore::settings();
+- settings->beginGroup(MAINWINDOW_KEY);
+- settings->setValue(CHANGED_DOCK_KEY, QStringList(changedDocks.toList()));
+- settings->setValue(STATE_KEY, theMainWindow->saveState(SettingsVersion));
+- settings->setValue(AUTOHIDE_TITLEBARS_KEY, theMainWindow->autoHideTitleBars());
+- settings->setValue(SHOW_CENTRALWIDGET_KEY, theMainWindow->isCentralWidgetShown());
+- settings->endGroup();
+ }
+
+ QWidget *DebuggerMainWindow::centralWidgetStack()
+@@ -525,100 +358,67 @@ DebuggerMainWindow *DebuggerMainWindow::instance()
+
+ Perspective *Perspective::findPerspective(const QString &perspectiveId)
+ {
+- QTC_ASSERT(theMainWindow, return nullptr);
+- return Utils::findOr(theMainWindow->d->m_perspectives, nullptr,
+- [perspectiveId](Perspective *perspective) {
+- return perspective && perspective->d->m_id == perspectiveId;
++ return Utils::findOr(theMainWindow->d->m_perspectives, nullptr, [&](Perspective *perspective) {
++ return perspective->d->m_id == perspectiveId;
+ });
+ }
+
+-bool Perspective::isCurrent() const
+-{
+- return theMainWindow->d->m_currentPerspective == this;
+-}
+-
+-QDockWidget *DebuggerMainWindowPrivate::dockForWidget(QWidget *widget) const
++void DebuggerMainWindowPrivate::resetCurrentPerspective()
+ {
+- QTC_ASSERT(widget, return nullptr);
+-
+- for (QDockWidget *dock : q->dockWidgets()) {
+- if (dock->widget() == widget)
+- return dock;
++ if (m_currentPerspective) {
++ m_currentPerspective->d->m_nonPersistenSettings.clear();
++ m_currentPerspective->d->hideToolBar();
+ }
+-
+- return nullptr;
++ depopulateCurrentPerspective();
++ populateCurrentPerspective();
++ if (m_currentPerspective)
++ m_currentPerspective->d->saveLayout();
+ }
+
+-void DebuggerMainWindowPrivate::resetCurrentPerspective()
++int DebuggerMainWindowPrivate::indexInChooser(Perspective *perspective) const
+ {
+- QTC_ASSERT(m_currentPerspective, return);
+- cleanDocks();
+- m_currentPerspective->d->resetPerspective();
+- setCentralWidget(m_currentPerspective->d->m_centralWidget);
++ return perspective ? m_perspectiveChooser->findData(perspective->d->m_id) : -1;
+ }
+
+-void DebuggerMainWindowPrivate::setCentralWidget(QWidget *widget)
++void DebuggerMainWindowPrivate::fixupLayoutIfNeeded()
+ {
+- if (widget) {
+- m_centralWidgetStack->addWidget(widget);
+- q->showCentralWidgetAction()->setText(widget->windowTitle());
+- } else {
+- m_centralWidgetStack->addWidget(m_editorPlaceHolder);
+- q->showCentralWidgetAction()->setText(DebuggerMainWindow::tr("Editor"));
++ // Evil workaround for QTCREATORBUG-21455: In some so far unknown situation
++ // the saveLayout/restoreLayout process leads to a situation where some docks
++ // do not end up below the perspective toolbar even though they were there
++ // initially, leading to an awkward dock layout.
++ // This here tries to detect the situation (sonmething else in the bottom
++ // area is at the right of the toolbar) "corrects" that by restoring the
++ // default layout.
++
++ if (m_toolBarDock->width() != q->width()) {
++ qDebug() << "Scrambled dock layout found. Resetting it.";
++ resetCurrentPerspective();
+ }
+ }
+
+-void PerspectivePrivate::resetPerspective()
++void DebuggerMainWindowPrivate::selectPerspective(Perspective *perspective)
+ {
+- showInnerToolBar();
++ QTC_ASSERT(perspective, return);
+
+- for (DockOperation &op : m_dockOperations) {
+- if (op.operationType == Perspective::Raise) {
+- QTC_ASSERT(op.dock, qCDebug(perspectivesLog) << op.name(); continue);
+- op.dock->raise();
+- } else {
+- op.setupLayout();
+- op.dock->setVisible(op.visibleByDefault);
+- qCDebug(perspectivesLog) << "SETTING " << op.name()
+- << " TO ACTIVE: " << op.visibleByDefault;
+- }
++ if (m_currentPerspective) {
++ m_currentPerspective->d->saveLayout();
++ m_currentPerspective->d->hideToolBar();
+ }
+-}
+
+-void DockOperation::setupLayout()
+-{
+- QTC_ASSERT(widget, return);
+- QTC_ASSERT(operationType != Perspective::Raise, return);
+- QTC_ASSERT(dock, return);
++ depopulateCurrentPerspective();
+
+- QDockWidget *anchor = nullptr;
+- if (anchorWidget)
+- anchor = theMainWindow->d->dockForWidget(anchorWidget);
+- else if (area == Qt::BottomDockWidgetArea)
+- anchor = theMainWindow->d->m_toolBarDock;
+-
+- if (anchor) {
+- switch (operationType) {
+- case Perspective::AddToTab:
+- theMainWindow->tabifyDockWidget(anchor, dock);
+- break;
+- case Perspective::SplitHorizontal:
+- theMainWindow->splitDockWidget(anchor, dock, Qt::Horizontal);
+- break;
+- case Perspective::SplitVertical:
+- theMainWindow->splitDockWidget(anchor, dock, Qt::Vertical);
+- break;
+- default:
+- break;
+- }
+- } else {
+- theMainWindow->addDockWidget(area, dock);
++ m_currentPerspective = perspective;
++
++ perspective->aboutToActivate();
++
++ populateCurrentPerspective();
++
++ if (m_currentPerspective) {
++ m_currentPerspective->d->restoreLayout();
++ fixupLayoutIfNeeded();
+ }
+-}
+
+-int DebuggerMainWindowPrivate::indexInChooser(Perspective *perspective) const
+-{
+- return perspective ? m_perspectiveChooser->findData(perspective->d->m_id) : -1;
++ updatePerspectiveChooserWidth();
+ }
+
+ void DebuggerMainWindowPrivate::updatePerspectiveChooserWidth()
+@@ -644,72 +444,111 @@ void DebuggerMainWindowPrivate::updatePerspectiveChooserWidth()
+ }
+ }
+
+-void DebuggerMainWindowPrivate::cleanDocks()
++void DebuggerMainWindowPrivate::depopulateCurrentPerspective()
+ {
+- m_statusLabel->clear();
+-
++ // Clean up old perspective.
+ for (QDockWidget *dock : q->dockWidgets()) {
+- if (dock != m_toolBarDock)
+- dock->setVisible(false);
++ 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;
++ }
+ }
+-}
+-
+-void PerspectivePrivate::depopulatePerspective()
+-{
+- ICore::removeAdditionalContext(context());
+- theMainWindow->d->m_centralWidgetStack
+- ->removeWidget(m_centralWidget ? m_centralWidget : theMainWindow->d->m_editorPlaceHolder);
+
+- theMainWindow->d->m_statusLabel->clear();
+-
+- for (QDockWidget *dock : theMainWindow->dockWidgets()) {
+- if (dock != theMainWindow->d->m_toolBarDock)
+- dock->setVisible(false);
++ if (m_currentPerspective) {
++ ICore::removeAdditionalContext(m_currentPerspective->context());
++ QWidget *central = m_currentPerspective->centralWidget();
++ m_centralWidgetStack->removeWidget(central ? central : m_editorPlaceHolder);
+ }
+-
+- hideInnerToolBar();
+ }
+
+-void PerspectivePrivate::saveAsLastUsedPerspective()
+-{
+- if (Perspective *parent = Perspective::findPerspective(m_parentPerspectiveId))
+- parent->d->m_lastActiveSubPerspectiveId = m_id;
+- else
+- m_lastActiveSubPerspectiveId.clear();
++void DebuggerMainWindowPrivate::populateCurrentPerspective()
++{
++ // Create dock widgets wrapping ther perspective's widgets.
++ QHash<QString, QDockWidget *> dockForDockId;
++ for (const DockOperation &op : m_currentPerspective->d->m_dockOperations) {
++ if (op.operationType == Perspective::Raise)
++ continue;
++ 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);
++ }
+
+- const QString &lastKey = m_parentPerspectiveId.isEmpty() ? m_id : m_parentPerspectiveId;
+- qCDebug(perspectivesLog) << "SAVE LAST USED PERSPECTIVE" << lastKey;
+- ICore::settings()->setValue(LAST_PERSPECTIVE_KEY, lastKey);
+-}
++ m_currentPerspective->d->showToolBar();
+
+-void PerspectivePrivate::populatePerspective()
+-{
+- showInnerToolBar();
++ // 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);
++ QTC_ASSERT(dock, continue);
++ if (op.operationType == Perspective::Raise) {
++ dock->raise();
++ continue;
++ }
++ QDockWidget *anchor = dockForDockId.value(op.anchorDockId);
++ if (!anchor && op.area == Qt::BottomDockWidgetArea) {
++ anchor = m_toolBarDock;
++ }
+
+- if (m_centralWidget) {
+- theMainWindow->d->m_centralWidgetStack->addWidget(m_centralWidget);
+- theMainWindow->showCentralWidgetAction()->setText(m_centralWidget->windowTitle());
+- } else {
+- theMainWindow->d->m_centralWidgetStack->addWidget(theMainWindow->d->m_editorPlaceHolder);
+- theMainWindow->showCentralWidgetAction()->setText(DebuggerMainWindow::tr("Editor"));
++ if (anchor) {
++ switch (op.operationType) {
++ case Perspective::AddToTab:
++ q->tabifyDockWidget(anchor, dock);
++ break;
++ case Perspective::SplitHorizontal:
++ q->splitDockWidget(anchor, dock, Qt::Horizontal);
++ break;
++ case Perspective::SplitVertical:
++ q->splitDockWidget(anchor, dock, Qt::Vertical);
++ break;
++ default:
++ break;
++ }
++ }
++ dock->setVisible(op.visibleByDefault);
+ }
+
+- ICore::addAdditionalContext(context());
++ QWidget *central = m_currentPerspective->centralWidget();
++ m_centralWidgetStack->addWidget(central ? central : m_editorPlaceHolder);
++ q->showCentralWidgetAction()->setText(central ? central->windowTitle()
++ : DebuggerMainWindow::tr("Editor"));
++
++ m_statusLabel->clear();
+
+- restoreLayout();
++ ICore::addAdditionalContext(m_currentPerspective->context());
+ }
+
+ // Perspective
+
+ Perspective::Perspective(const QString &id, const QString &name,
+ const QString &parentPerspectiveId,
+- const QString &settingsId)
++ const QString &subPerspectiveType)
+ : d(new PerspectivePrivate)
+ {
++ const bool shouldPersist = parentPerspectiveId.isEmpty();
+ d->m_id = id;
+ d->m_name = name;
+ d->m_parentPerspectiveId = parentPerspectiveId;
+- d->m_settingsId = settingsId;
++ d->m_subPerspectiveType = subPerspectiveType;
++ d->m_shouldPersistChecker = [shouldPersist] { return shouldPersist; };
+
+ DebuggerMainWindow::ensureMainWindowExists();
+ theMainWindow->d->registerPerspective(this);
+@@ -726,8 +565,12 @@ Perspective::Perspective(const QString &id, const QString &name,
+ Perspective::~Perspective()
+ {
+ if (theMainWindow) {
++ d->saveLayout();
++
+ delete d->m_innerToolBar;
+ d->m_innerToolBar = nullptr;
++
++ theMainWindow->d->destroyPerspective(this);
+ }
+ delete d;
+ }
+@@ -753,6 +596,12 @@ void Perspective::setAboutToActivateCallback(const Perspective::Callback &cb)
+ d->m_aboutToActivateCallback = cb;
+ }
+
++void Perspective::aboutToActivate() const
++{
++ if (d->m_aboutToActivateCallback)
++ d->m_aboutToActivateCallback();
++}
++
+ void Perspective::setEnabled(bool enabled)
+ {
+ QTC_ASSERT(theMainWindow, return);
+@@ -805,24 +654,34 @@ void Perspective::addToolbarSeparator()
+ d->m_innerToolBarLayout->addWidget(new StyledSeparator(d->m_innerToolBar));
+ }
+
++void Perspective::setShouldPersistChecker(const ShouldPersistChecker &checker)
++{
++ d->m_shouldPersistChecker = checker;
++}
++
+ QWidget *Perspective::centralWidget() const
+ {
+ return d->m_centralWidget;
+ }
+
+-Context PerspectivePrivate::context() const
++Perspective *Perspective::currentPerspective()
+ {
+- return Context(Id::fromName(m_id.toUtf8()));
++ return theMainWindow ? theMainWindow->d->m_currentPerspective : nullptr;
+ }
+
+-void PerspectivePrivate::showInnerToolBar()
++Context Perspective::context() const
++{
++ return Context(Id::fromName(d->m_id.toUtf8()));
++}
++
++void PerspectivePrivate::showToolBar()
+ {
+ m_innerToolBar->setVisible(true);
+ if (m_switcher)
+ m_switcher->setVisible(true);
+ }
+
+-void PerspectivePrivate::hideInnerToolBar()
++void PerspectivePrivate::hideToolBar()
+ {
+ QTC_ASSERT(m_innerToolBar, return);
+ m_innerToolBar->setVisible(false);
+@@ -839,131 +698,63 @@ void Perspective::addWindow(QWidget *widget,
+ QTC_ASSERT(widget, return);
+ DockOperation op;
+ op.widget = widget;
++ if (anchorWidget)
++ op.anchorDockId = anchorWidget->objectName();
+ op.operationType = type;
+- op.anchorWidget = anchorWidget;
+ op.visibleByDefault = visibleByDefault;
+ op.area = area;
+-
+- if (op.operationType != Perspective::Raise) {
+- qCDebug(perspectivesLog) << "CREATING DOCK " << op.name()
+- << "DEFAULT: " << op.visibleByDefault;
+- op.dock = theMainWindow->addDockForWidget(op.widget);
+- op.commandId = Id("Dock.").withSuffix(op.name());
+- if (theMainWindow->restoreDockWidget(op.dock)) {
+- qCDebug(perspectivesLog) << "RESTORED SUCCESSFULLY";
+- } else {
+- qCDebug(perspectivesLog) << "COULD NOT RESTORE";
+- op.setupLayout();
+- }
+- op.dock->setVisible(false);
+- op.dock->toggleViewAction()->setText(op.dock->windowTitle());
+-
+- QObject::connect(op.dock->toggleViewAction(), &QAction::changed, op.dock, [this, op] {
+- qCDebug(perspectivesLog) << "CHANGED: " << op.name()
+- << "ACTION CHECKED: " << op.dock->toggleViewAction()->isChecked();
+- });
+-
+- Command *cmd = ActionManager::registerAction(op.dock->toggleViewAction(),
+- op.commandId, d->context());
+- cmd->setAttribute(Command::CA_Hide);
+- ActionManager::actionContainer(Core::Constants::M_WINDOW_VIEWS)->addAction(cmd);
+- }
+-
+- op.visibleByUser = op.visibleByDefault;
+- if (theMainWindow->d->m_persistentChangedDocks.contains(op.name())) {
+- op.visibleByUser = !op.visibleByUser;
+- qCDebug(perspectivesLog) << "*** NON-DEFAULT USER: " << op.visibleByUser;
+- } else {
+- qCDebug(perspectivesLog) << "DEFAULT USER";
+- }
+-
+ d->m_dockOperations.append(op);
+ }
+
+-void Perspective::destroy()
+-{
+- theMainWindow->d->destroyPerspective(this);
+-}
+-
+-void Perspective::rampDownAsCurrent()
+-{
+- QTC_ASSERT(this == theMainWindow->d->m_currentPerspective, return);
+- d->saveLayout();
+- d->depopulatePerspective();
+- theMainWindow->d->setCurrentPerspective(nullptr);
+-
+- Debugger::Internal::EngineManager::updatePerspectives();
+-}
+-
+-void Perspective::rampUpAsCurrent()
+-{
+- if (d->m_aboutToActivateCallback)
+- d->m_aboutToActivateCallback();
+-
+- QTC_ASSERT(theMainWindow->d->m_currentPerspective == nullptr, return);
+- theMainWindow->d->setCurrentPerspective(this);
+- QTC_ASSERT(theMainWindow->d->m_currentPerspective == this, return);
+-
+- d->populatePerspective();
+-
+- theMainWindow->d->updatePerspectiveChooserWidth();
+-
+- d->saveAsLastUsedPerspective();
+-
+- Debugger::Internal::EngineManager::updatePerspectives();
+-}
+-
+ void Perspective::select()
+ {
+ Debugger::Internal::EngineManager::activateDebugMode();
+-
+- if (theMainWindow->d->m_currentPerspective == this)
++ if (Perspective::currentPerspective() == this)
+ return;
++ theMainWindow->d->selectPerspective(this);
++ if (Perspective *parent = Perspective::findPerspective(d->m_parentPerspectiveId))
++ parent->d->m_lastActiveSubPerspectiveId = d->m_id;
++ else
++ d->m_lastActiveSubPerspectiveId.clear();
+
+- if (theMainWindow->d->m_currentPerspective)
+- theMainWindow->d->m_currentPerspective->rampDownAsCurrent();
+- QTC_CHECK(theMainWindow->d->m_currentPerspective == nullptr);
+-
+- rampUpAsCurrent();
++ const QString &lastKey = d->m_parentPerspectiveId.isEmpty() ? d->m_id : d->m_parentPerspectiveId;
++ ICore::settings()->setValue(LAST_PERSPECTIVE_KEY, lastKey);
+ }
+
+ void PerspectivePrivate::restoreLayout()
+ {
+- qCDebug(perspectivesLog) << "PERSPECTIVE" << m_id << "RESTORING LAYOUT FROM " << settingsId();
+- for (DockOperation &op : m_dockOperations) {
+- if (op.operationType != Perspective::Raise) {
+- QTC_ASSERT(op.dock, continue);
+- const bool active = op.visibleByUser;
+- op.dock->toggleViewAction()->setChecked(active);
+- op.dock->setVisible(active);
+- qCDebug(perspectivesLog) << "RESTORE DOCK " << op.name() << "ACTIVE: " << active
+- << (active == op.visibleByDefault ? "DEFAULT USER" : "*** NON-DEFAULT USER");
+- }
++ if (m_nonPersistenSettings.isEmpty()) {
++ //qDebug() << "PERSPECTIVE" << m_id << "RESTORE PERSISTENT FROM " << settingsId();
++ QSettings *settings = ICore::settings();
++ settings->beginGroup(settingsId());
++ theMainWindow->restoreSettings(settings);
++ settings->endGroup();
++ m_nonPersistenSettings = theMainWindow->saveSettings();
++ } else {
++ //qDebug() << "PERSPECTIVE" << m_id << "RESTORE FROM LOCAL TEMP";
++ theMainWindow->restoreSettings(m_nonPersistenSettings);
+ }
+ }
+
+ void PerspectivePrivate::saveLayout()
+ {
+- qCDebug(perspectivesLog) << "PERSPECTIVE" << m_id << "SAVE LAYOUT TO " << settingsId();
+- for (DockOperation &op : m_dockOperations) {
+- if (op.operationType != Perspective::Raise) {
+- QTC_ASSERT(op.dock, continue);
+- QTC_ASSERT(op.widget, continue);
+- const bool active = op.dock->toggleViewAction()->isChecked();
+- op.visibleByUser = active;
+- if (active == op.visibleByDefault)
+- theMainWindow->d->m_persistentChangedDocks.remove(op.name());
+- else
+- theMainWindow->d->m_persistentChangedDocks.insert(op.name());
+- qCDebug(perspectivesLog) << "SAVE DOCK " << op.name() << "ACTIVE: " << active
+- << (active == op.visibleByDefault ? "DEFAULT USER" : "*** NON-DEFAULT USER");
+- }
++ //qDebug() << "PERSPECTIVE" << m_id << "SAVE LOCAL TEMP";
++ m_nonPersistenSettings = theMainWindow->saveSettings();
++
++ if (m_shouldPersistChecker()) {
++ //qDebug() << "PERSPECTIVE" << m_id << "SAVE PERSISTENT TO " << settingsId();
++ QSettings *settings = ICore::settings();
++ settings->beginGroup(settingsId());
++ theMainWindow->saveSettings(settings);
++ settings->endGroup();
++ } else {
++ //qDebug() << "PERSPECTIVE" << m_id << "NOT PERSISTENT";
+ }
+ }
+
+ QString PerspectivePrivate::settingsId() const
+ {
+- return m_settingsId.isEmpty() ? m_id : m_settingsId;
++ return m_parentPerspectiveId.isEmpty() ? m_id : (m_parentPerspectiveId + '.' + m_subPerspectiveType);
+ }
+
+ // ToolbarAction
+diff --git a/src/plugins/debugger/debuggermainwindow.h b/src/plugins/debugger/debuggermainwindow.h
+index 116eb73717..98ff0a37d1 100644
+--- a/src/plugins/debugger/debuggermainwindow.h
++++ b/src/plugins/debugger/debuggermainwindow.h
+@@ -59,12 +59,12 @@ public:
+ QPointer<QToolButton> m_toolButton;
+ };
+
+-class DEBUGGER_EXPORT Perspective : public QObject
++class DEBUGGER_EXPORT Perspective
+ {
+ public:
+ Perspective(const QString &id, const QString &name,
+ const QString &parentPerspectiveId = QString(),
+- const QString &settingId = QString());
++ const QString &subPerspectiveType = QString());
+ ~Perspective();
+
+ enum OperationType { SplitVertical, SplitHorizontal, AddToTab, Raise };
+@@ -92,26 +92,26 @@ public:
+
+ using Callback = std::function<void()>;
+ void setAboutToActivateCallback(const Callback &cb);
++ void aboutToActivate() const;
+
+ void setEnabled(bool enabled);
+
+ void select();
+- void destroy();
+
++ static Perspective *currentPerspective();
+ static Perspective *findPerspective(const QString &perspectiveId);
+
+- bool isCurrent() const;
++ Core::Context context() const;
+
+-private:
+- void rampDownAsCurrent();
+- void rampUpAsCurrent();
++ void showToolBar();
++ void hideToolBar();
+
++private:
+ Perspective(const Perspective &) = delete;
+ void operator=(const Perspective &) = delete;
+
+ friend class DebuggerMainWindow;
+ friend class DebuggerMainWindowPrivate;
+- friend class PerspectivePrivate;
+ class PerspectivePrivate *d = nullptr;
+ };
+
+@@ -132,20 +132,12 @@ public:
+ static QWidget *centralWidgetStack();
+ void addSubPerspectiveSwitcher(QWidget *widget);
+
+- static void savePersistentSettings();
+- static void restorePersistentSettings();
+-
+- static Perspective *currentPerspective();
+-
+ private:
+ DebuggerMainWindow();
+ ~DebuggerMainWindow() override;
+
+- void contextMenuEvent(QContextMenuEvent *ev) override;
+-
+ friend class Perspective;
+ friend class PerspectivePrivate;
+- friend class DockOperation;
+ class DebuggerMainWindowPrivate *d = nullptr;
+ };
+
+diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp
+index 322a87277c..89c0dff58f 100644
+--- a/src/plugins/debugger/debuggerplugin.cpp
++++ b/src/plugins/debugger/debuggerplugin.cpp
+@@ -1046,7 +1046,7 @@ bool DebuggerPluginPrivate::initialize(const QStringList &arguments,
+ m_breakpointManagerView->setSpanColumn(BreakpointFunctionColumn);
+ m_breakpointManagerWindow = addSearch(m_breakpointManagerView);
+ m_breakpointManagerWindow->setWindowTitle(tr("Breakpoint Preset"));
+- m_breakpointManagerWindow->setObjectName("Debugger.Docks.BreakpointManager");
++ m_breakpointManagerWindow->setObjectName(DOCKWIDGET_BREAKPOINTMANAGER);
+ addLabel(m_breakpointManagerWindow, m_breakpointManagerWindow->windowTitle());
+
+
+@@ -1058,7 +1058,7 @@ bool DebuggerPluginPrivate::initialize(const QStringList &arguments,
+ m_engineManagerView->setModel(m_engineManager.model());
+ m_engineManagerWindow = addSearch(m_engineManagerView);
+ m_engineManagerWindow->setWindowTitle(tr("Debugger Perspectives"));
+- m_engineManagerWindow->setObjectName("Debugger.Docks.Snapshots");
++ m_engineManagerWindow->setObjectName(DOCKWIDGET_ENGINEMANAGER);
+ addLabel(m_engineManagerWindow, m_engineManagerWindow->windowTitle());
+
+ // Logging
+@@ -1357,8 +1357,7 @@ bool DebuggerPluginPrivate::initialize(const QStringList &arguments,
+ DebuggerMainWindow::leaveDebugMode();
+ });
+
+- connect(ModeManager::instance(), &ModeManager::currentModeChanged, [](Id mode, Id oldMode) {
+- QTC_ASSERT(mode != oldMode, return);
++ connect(ModeManager::instance(), &ModeManager::currentModeChanged, this, [](Id mode) {
+ if (mode == MODE_DEBUG) {
+ DebuggerMainWindow::enterDebugMode();
+ if (IEditor *editor = EditorManager::currentEditor())
+@@ -1523,7 +1522,7 @@ void DebuggerPluginPrivate::updatePresetState()
+ } else {
+ // The startup phase should be over once we are here.
+ // But treat it as 'undisturbable if we are here by accident.
+- //QTC_CHECK(state != DebuggerNotReady);
++ QTC_CHECK(state != DebuggerNotReady);
+ // Everything else is "undisturbable".
+ m_startAction.setEnabled(false);
+ m_debugWithoutDeployAction.setEnabled(false);
+@@ -1561,7 +1560,7 @@ void DebuggerPluginPrivate::onStartupProjectChanged(Project *project)
+ }
+ for (DebuggerEngine *engine : EngineManager::engines()) {
+ // Run controls might be deleted during exit.
+- engine->updateState();
++ engine->updateState(false);
+ }
+
+ updatePresetState();
+@@ -2016,9 +2015,11 @@ void DebuggerPluginPrivate::aboutToShutdown()
+ m_shutdownTimer.setInterval(0);
+ m_shutdownTimer.setSingleShot(true);
+ connect(&m_shutdownTimer, &QTimer::timeout, this, &DebuggerPluginPrivate::doShutdown);
+- if (EngineManager::shutDown()) {
+- // If any engine is aborting we give them extra three seconds.
+- m_shutdownTimer.setInterval(3000);
++ for (DebuggerEngine *engine : m_engineManager.engines()) {
++ if (engine && engine->state() != Debugger::DebuggerNotReady) {
++ engine->abortDebugger();
++ m_shutdownTimer.setInterval(3000);
++ }
+ }
+ m_shutdownTimer.start();
+ }
+diff --git a/src/plugins/debugger/debuggerruncontrol.cpp b/src/plugins/debugger/debuggerruncontrol.cpp
+index ca76e8cfe1..c72fcb6228 100644
+--- a/src/plugins/debugger/debuggerruncontrol.cpp
++++ b/src/plugins/debugger/debuggerruncontrol.cpp
+@@ -728,6 +728,8 @@ void DebuggerRunTool::stop()
+
+ void DebuggerRunTool::handleEngineStarted(DebuggerEngine *engine)
+ {
++ EngineManager::activateEngine(engine);
++
+ // Correct:
+ // if (--d->engineStartsNeeded == 0) {
+ // EngineManager::activateDebugMode();
+diff --git a/src/plugins/debugger/enginemanager.cpp b/src/plugins/debugger/enginemanager.cpp
+index 0ca42d64a7..68a31bde14 100644
+--- a/src/plugins/debugger/enginemanager.cpp
++++ b/src/plugins/debugger/enginemanager.cpp
+@@ -155,14 +155,14 @@ public:
+ }
+
+ EngineItem *findEngineItem(DebuggerEngine *engine);
++ void activateEngine(DebuggerEngine *engine);
+ void activateEngineItem(EngineItem *engineItem);
+ void activateEngineByIndex(int index);
+ void selectUiForCurrentEngine();
+ void updateEngineChooserVisibility();
+- void updatePerspectives();
+
+ TreeModel<TypedTreeItem<EngineItem>, EngineItem> m_engineModel;
+- QPointer<EngineItem> m_currentItem; // The primary information is DebuggerMainWindow::d->m_currentPerspective
++ QPointer<EngineItem> m_currentItem;
+ Core::Id m_previousMode;
+ QPointer<QComboBox> m_engineChooser;
+ bool m_shuttingDown = false;
+@@ -200,11 +200,6 @@ QWidget *EngineManager::engineChooser()
+ return d->m_engineChooser;
+ }
+
+-void EngineManager::updatePerspectives()
+-{
+- d->updatePerspectives();
+-}
+-
+ EngineManager::~EngineManager()
+ {
+ theEngineManager = nullptr;
+@@ -221,6 +216,11 @@ QAbstractItemModel *EngineManager::model()
+ return &d->m_engineModel;
+ }
+
++void EngineManager::activateEngine(DebuggerEngine *engine)
++{
++ d->activateEngine(engine);
++}
++
+ QVariant EngineItem::data(int column, int role) const
+ {
+ if (m_engine) {
+@@ -281,7 +281,7 @@ bool EngineItem::setData(int row, const QVariant &value, int role)
+
+ if (role == BaseTreeView::ItemActivatedRole) {
+ EngineItem *engineItem = d->findEngineItem(m_engine);
+- d->activateEngineByIndex(engineItem->indexInParent());
++ d->activateEngineItem(engineItem);
+ return true;
+ }
+
+@@ -324,27 +324,21 @@ bool EngineItem::setData(int row, const QVariant &value, int role)
+
+ void EngineManagerPrivate::activateEngineByIndex(int index)
+ {
+- // The actual activation is triggered indirectly via the perspective change.
+- Perspective *perspective = nullptr;
+- if (index == 0) {
+- perspective = Perspective::findPerspective(Debugger::Constants::PRESET_PERSPECTIVE_ID);
+- } else {
+- EngineItem *engineItem = m_engineModel.rootItem()->childAt(index);
+- QTC_ASSERT(engineItem, return);
+- QTC_ASSERT(engineItem->m_engine, return);
+- perspective = engineItem->m_engine->perspective();
+- }
+-
+- QTC_ASSERT(perspective, return);
+- perspective->select();
++ activateEngineItem(m_engineModel.rootItem()->childAt(index));
+ }
+
+ void EngineManagerPrivate::activateEngineItem(EngineItem *engineItem)
+ {
+- if (m_currentItem == engineItem)
+- return;
++ Context previousContext;
++ if (m_currentItem) {
++ if (DebuggerEngine *engine = m_currentItem->m_engine) {
++ previousContext.add(engine->languageContext());
++ previousContext.add(engine->debuggerContext());
++ } else {
++ previousContext.add(Context(Constants::C_DEBUGGER_NOTRUNNING));
++ }
++ }
+
+- QTC_ASSERT(engineItem, return);
+ m_currentItem = engineItem;
+
+ Context newContext;
+@@ -357,13 +351,7 @@ void EngineManagerPrivate::activateEngineItem(EngineItem *engineItem)
+ }
+ }
+
+- ICore::updateAdditionalContexts(m_currentAdditionalContext, newContext);
+- m_currentAdditionalContext = newContext;
+-
+- // In case this was triggered externally by some Perspective::select() call.
+- const int idx = engineItem->indexInParent();
+- m_engineChooser->setCurrentIndex(idx);
+-
++ ICore::updateAdditionalContexts(previousContext, newContext);
+ selectUiForCurrentEngine();
+ }
+
+@@ -372,7 +360,12 @@ void EngineManagerPrivate::selectUiForCurrentEngine()
+ if (ModeManager::currentModeId() != Constants::MODE_DEBUG)
+ return;
+
++ Perspective *perspective = nullptr;
+ int row = 0;
++
++ if (m_currentItem && m_currentItem->m_engine)
++ perspective = m_currentItem->m_engine->perspective();
++
+ if (m_currentItem)
+ row = m_engineModel.rootItem()->indexOf(m_currentItem);
+
+@@ -385,6 +378,12 @@ void EngineManagerPrivate::selectUiForCurrentEngine()
+ QStyle::CT_ComboBox, &option, sz).width();
+ m_engineChooser->setFixedWidth(width);
+
++ if (!perspective)
++ perspective = Perspective::findPerspective(Debugger::Constants::PRESET_PERSPECTIVE_ID);
++
++ QTC_ASSERT(perspective, return);
++ perspective->select();
++
+ m_engineModel.rootItem()->forFirstLevelChildren([this](EngineItem *engineItem) {
+ if (engineItem && engineItem->m_engine)
+ engineItem->m_engine->updateUi(engineItem == m_currentItem);
+@@ -400,6 +399,12 @@ EngineItem *EngineManagerPrivate::findEngineItem(DebuggerEngine *engine)
+ });
+ }
+
++void EngineManagerPrivate::activateEngine(DebuggerEngine *engine)
++{
++ EngineItem *engineItem = findEngineItem(engine);
++ activateEngineItem(engineItem);
++}
++
+ void EngineManagerPrivate::updateEngineChooserVisibility()
+ {
+ // Show it if there's more than one option (i.e. not the preset engine only)
+@@ -409,48 +414,12 @@ void EngineManagerPrivate::updateEngineChooserVisibility()
+ }
+ }
+
+-void EngineManagerPrivate::updatePerspectives()
+-{
+- d->updateEngineChooserVisibility();
+-
+- Perspective *current = DebuggerMainWindow::currentPerspective();
+- if (!current) {
+- return;
+- }
+-
+- m_engineModel.rootItem()->forFirstLevelChildren([this, current](EngineItem *engineItem) {
+- if (engineItem == m_currentItem)
+- return;
+-
+- bool shouldBeActive = false;
+- if (engineItem->m_engine) {
+- // Normal engine.
+- shouldBeActive = engineItem->m_engine->perspective()->isCurrent();
+- } else {
+- // Preset.
+- shouldBeActive = current->id() == Debugger::Constants::PRESET_PERSPECTIVE_ID;
+- }
+-
+- if (shouldBeActive && engineItem != m_currentItem)
+- activateEngineItem(engineItem);
+- });
+-}
+-
+-QString EngineManager::registerEngine(DebuggerEngine *engine)
++void EngineManager::registerEngine(DebuggerEngine *engine)
+ {
+ auto engineItem = new EngineItem;
+ engineItem->m_engine = engine;
+ d->m_engineModel.rootItem()->appendChild(engineItem);
+ d->updateEngineChooserVisibility();
+- return QString::number(d->m_engineModel.rootItem()->childCount());
+-}
+-
+-void EngineManager::unregisterEngine(DebuggerEngine *engine)
+-{
+- EngineItem *engineItem = d->findEngineItem(engine);
+- QTC_ASSERT(engineItem, return);
+- d->m_engineModel.destroyItem(engineItem);
+- d->updateEngineChooserVisibility();
+ }
+
+ void EngineManager::activateDebugMode()
+@@ -473,6 +442,33 @@ void EngineManager::deactivateDebugMode()
+ }
+ }
+
++bool EngineManager::isLastOf(const QString &type)
++{
++ int count = 0;
++ d->m_engineModel.rootItem()->forFirstLevelChildren([&](EngineItem *engineItem) {
++ if (engineItem && engineItem->m_engine)
++ count += (engineItem->m_engine->debuggerName() == type);
++ });
++ return count == 1;
++}
++
++void EngineManager::unregisterEngine(DebuggerEngine *engine)
++{
++ if (ModeManager::currentModeId() == Constants::MODE_DEBUG) {
++ if (Perspective *parent = Perspective::findPerspective(Constants::PRESET_PERSPECTIVE_ID))
++ parent->select();
++ }
++
++ d->activateEngineItem(d->m_engineModel.rootItem()->childAt(0)); // Preset.
++
++ // Could be that the run controls died before it was appended.
++ if (auto engineItem = d->findEngineItem(engine))
++ d->m_engineModel.destroyItem(engineItem);
++
++ d->updateEngineChooserVisibility();
++ emit theEngineManager->currentEngineChanged();
++}
++
+ QList<QPointer<DebuggerEngine>> EngineManager::engines()
+ {
+ QList<QPointer<DebuggerEngine>> result;
+@@ -488,18 +484,5 @@ QPointer<DebuggerEngine> EngineManager::currentEngine()
+ return d->m_currentItem ? d->m_currentItem->m_engine : nullptr;
+ }
+
+-bool EngineManager::shutDown()
+-{
+- d->m_shuttingDown = true;
+- bool anyEngineAborting = false;
+- for (DebuggerEngine *engine : EngineManager::engines()) {
+- if (engine && engine->state() != Debugger::DebuggerNotReady) {
+- engine->abortDebugger();
+- anyEngineAborting = true;
+- }
+- }
+- return anyEngineAborting;
+-}
+-
+ } // namespace Internal
+ } // namespace Debugger
+diff --git a/src/plugins/debugger/enginemanager.h b/src/plugins/debugger/enginemanager.h
+index 08549ba711..a1ee76c60b 100644
+--- a/src/plugins/debugger/enginemanager.h
++++ b/src/plugins/debugger/enginemanager.h
+@@ -45,19 +45,17 @@ public:
+ static EngineManager *instance();
+ static QAbstractItemModel *model();
+
+- static QString registerEngine(DebuggerEngine *engine);
++ static void registerEngine(DebuggerEngine *engine);
+ static void unregisterEngine(DebuggerEngine *engine);
+-
++ static void activateEngine(DebuggerEngine *engine);
+ static void activateDebugMode();
+ static void deactivateDebugMode();
++ static bool isLastOf(const QString &type);
+
+ static QList<QPointer<DebuggerEngine> > engines();
+ static QPointer<DebuggerEngine> currentEngine();
+
+ static QWidget *engineChooser();
+- static void updatePerspectives();
+-
+- static bool shutDown(); // Return true if some engine is being forced to shut down.
+
+ signals:
+ void engineStateChanged(DebuggerEngine *engine);
+diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp
+index 796416374a..8d2af5008a 100644
+--- a/src/plugins/debugger/gdb/gdbengine.cpp
++++ b/src/plugins/debugger/gdb/gdbengine.cpp
+@@ -2953,7 +2953,7 @@ void GdbEngine::handleThreadInfo(const DebuggerResponse &response)
+ if (response.resultClass == ResultDone) {
+ ThreadsHandler *handler = threadsHandler();
+ handler->setThreads(response.data);
+- updateState(); // Adjust Threads combobox.
++ updateState(false); // Adjust Threads combobox.
+ if (boolSetting(ShowThreadNames)) {
+ runCommand({"threadnames " + action(MaximalStackDepth)->value().toString(),
+ Discardable, CB(handleThreadNames)});
+@@ -2993,7 +2993,7 @@ void GdbEngine::handleThreadNames(const DebuggerResponse &response)
+ thread.name = decodeData(name["value"].data(), name["valueencoded"].data());
+ handler->updateThread(thread);
+ }
+- updateState();
++ updateState(false);
+ }
+ }
+
diff --git a/qtcreator-occurrences-fix.patch b/qtcreator-occurrences-fix.patch
deleted file mode 100644
index d6af0d6f6d66..000000000000
--- a/qtcreator-occurrences-fix.patch
+++ /dev/null
@@ -1,104 +0,0 @@
-diff --git a/src/plugins/texteditor/fontsettings.cpp b/src/plugins/texteditor/fontsettings.cpp
-index bc8d8c4d1a..a7203e8973 100644
---- a/src/plugins/texteditor/fontsettings.cpp
-+++ b/src/plugins/texteditor/fontsettings.cpp
-@@ -143,6 +143,14 @@ uint qHash(const TextStyle &textStyle)
- return ::qHash(quint8(textStyle));
- }
-
-+static bool isOverlayCategory(TextStyle category)
-+{
-+ return category == C_OCCURRENCES
-+ || category == C_OCCURRENCES_RENAME
-+ || category == C_SEARCH_RESULT
-+ || category == C_PARENTHESES_MISMATCH;
-+}
-+
- /**
- * Returns the QTextCharFormat of the given format category.
- */
-@@ -166,18 +174,18 @@ QTextCharFormat FontSettings::toTextCharFormat(TextStyle category) const
- "Unused variable"));
- }
-
-- if (f.foreground().isValid()
-- && category != C_OCCURRENCES
-- && category != C_OCCURRENCES_RENAME
-- && category != C_SEARCH_RESULT
-- && category != C_PARENTHESES_MISMATCH)
-+ if (f.foreground().isValid() && !isOverlayCategory(category))
- tf.setForeground(f.foreground());
-- if (f.background().isValid() && (category == C_TEXT || f.background() != m_scheme.formatFor(C_TEXT).background()))
-- tf.setBackground(f.background());
--
-- // underline does not need to fill without having background color
-- if (f.underlineStyle() != QTextCharFormat::NoUnderline && !f.background().isValid())
-- tf.setBackground(QBrush(Qt::BrushStyle::NoBrush));
-+ if (f.background().isValid()) {
-+ if (category == C_TEXT || f.background() != m_scheme.formatFor(C_TEXT).background())
-+ tf.setBackground(f.background());
-+ } else if (isOverlayCategory(category)) {
-+ // overlays without a background schouldn't get painted
-+ tf.setBackground(QColor());
-+ } else if (f.underlineStyle() != QTextCharFormat::NoUnderline) {
-+ // underline does not need to fill without having background color
-+ tf.setBackground(Qt::BrushStyle::NoBrush);
-+ }
-
- tf.setFontWeight(f.bold() ? QFont::Bold : QFont::Normal);
- tf.setFontItalic(f.italic());
-diff --git a/src/plugins/texteditor/texteditoroverlay.cpp b/src/plugins/texteditor/texteditoroverlay.cpp
-index 60fe5cc99e..a33ca13810 100644
---- a/src/plugins/texteditor/texteditoroverlay.cpp
-+++ b/src/plugins/texteditor/texteditoroverlay.cpp
-@@ -323,9 +323,7 @@ void TextEditorOverlay::paintSelection(QPainter *painter,
- const QColor &bg = selection.m_bg;
-
-
-- if (begin.isNull()
-- || end.isNull()
-- || begin.position() > end.position())
-+ if (begin.isNull() || end.isNull() || begin.position() > end.position() || !bg.isValid())
- return;
-
- QPainterPath path = createSelectionPath(begin, end, m_editor->viewport()->rect());
-@@ -339,25 +337,21 @@ void TextEditorOverlay::paintSelection(QPainter *painter,
-
- QRectF pathRect = path.controlPointRect();
-
-- if (bg.isValid()) {
-- if (!m_alpha || begin.blockNumber() != end.blockNumber()) {
-- // gradients are too slow for larger selections :(
-- QColor col = bg;
-- if (m_alpha)
-- col.setAlpha(50);
-- painter->setBrush(col);
-- } else {
-- QLinearGradient linearGrad(pathRect.topLeft(), pathRect.bottomLeft());
-- QColor col1 = fg.lighter(150);
-- col1.setAlpha(20);
-- QColor col2 = fg;
-- col2.setAlpha(80);
-- linearGrad.setColorAt(0, col1);
-- linearGrad.setColorAt(1, col2);
-- painter->setBrush(QBrush(linearGrad));
-- }
-+ if (!m_alpha || begin.blockNumber() != end.blockNumber()) {
-+ // gradients are too slow for larger selections :(
-+ QColor col = bg;
-+ if (m_alpha)
-+ col.setAlpha(50);
-+ painter->setBrush(col);
- } else {
-- painter->setBrush(QBrush());
-+ QLinearGradient linearGrad(pathRect.topLeft(), pathRect.bottomLeft());
-+ QColor col1 = fg.lighter(150);
-+ col1.setAlpha(20);
-+ QColor col2 = fg;
-+ col2.setAlpha(80);
-+ linearGrad.setColorAt(0, col1);
-+ linearGrad.setColorAt(1, col2);
-+ painter->setBrush(QBrush(linearGrad));
- }
-
- painter->setRenderHint(QPainter::Antialiasing);
diff --git a/qtcreator-preload-plugins.patch b/qtcreator-preload-plugins.patch
new file mode 100644
index 000000000000..f4772dd05de9
--- /dev/null
+++ b/qtcreator-preload-plugins.patch
@@ -0,0 +1,21 @@
+diff --git a/src/plugins/clangtools/clangtidyclazyrunner.cpp b/src/plugins/clangtools/clangtidyclazyrunner.cpp
+index a580704243..7a8740a5cc 100644
+--- a/src/plugins/clangtools/clangtidyclazyrunner.cpp
++++ b/src/plugins/clangtools/clangtidyclazyrunner.cpp
+@@ -76,6 +76,7 @@ QStringList ClangTidyClazyRunner::constructCommandLineArguments(const QStringLis
+
+ const ClangDiagnosticConfig::TidyMode tidyMode = m_diagnosticConfig.clangTidyMode();
+ if (tidyMode != ClangDiagnosticConfig::TidyMode::Disabled) {
++ arguments << XclangArgs({"-load", "libclangTidyPlugin.so"});
+ arguments << XclangArgs({"-add-plugin", "clang-tidy"});
+ if (tidyMode != ClangDiagnosticConfig::TidyMode::File) {
+ const QString tidyChecks = m_diagnosticConfig.clangTidyChecks();
+@@ -85,7 +86,7 @@ QStringList ClangTidyClazyRunner::constructCommandLineArguments(const QStringLis
+
+ const QString clazyChecks = m_diagnosticConfig.clazyChecks();
+ if (!clazyChecks.isEmpty()) {
+- arguments << XclangArgs({"-add-plugin",
++ arguments << XclangArgs({"-load", "ClazyPlugin.so", "-add-plugin",
+ "clazy",
+ "-plugin-arg-clazy",
+ "enable-all-fixits",
diff --git a/qtcreator-theme-fixes.patch b/qtcreator-theme-fixes.patch
deleted file mode 100644
index 0905939ae89b..000000000000
--- a/qtcreator-theme-fixes.patch
+++ /dev/null
@@ -1,308 +0,0 @@
-diff --git a/share/qtcreator/themes/dark.creatortheme b/share/qtcreator/themes/dark.creatortheme
-index ef19fc9fa6..41439ff22a 100644
---- a/share/qtcreator/themes/dark.creatortheme
-+++ b/share/qtcreator/themes/dark.creatortheme
-@@ -7,8 +7,10 @@ DefaultTextEditorColorScheme=dark.xml
- shadowBackground=ff232323
- text=ffe7e7e7
- textDisabled=7fffffff
-+textHighlighted=ffe7e7e7
- hoverBackground=18ffffff
--selectedBackground=66000000
-+selectedBackground=aa1f75cc
-+selectedBackgroundText=aa1f75cc
- normalBackground=ff333333
- alternateBackground=ff515151
- error=ffd84044
-@@ -48,6 +50,7 @@ DoubleTabWidget2ndTabInactiveTextColor=textDisabled
- EditorPlaceholderColor=normalBackground
- FancyToolBarSeparatorColor=43ffffff
- FancyTabBarBackgroundColor=shadowBackground
-+FancyTabBarSelectedBackgroundColor=88000000
- FancyTabWidgetDisabledSelectedTextColor=textDisabled
- FancyTabWidgetDisabledUnselectedTextColor=textDisabled
- FancyTabWidgetEnabledSelectedTextColor=text
-@@ -118,7 +121,7 @@ SplitterColor=splitterColor
- TextColorDisabled=textDisabled
- TextColorError=ffff4040
- TextColorHighlight=ffff0000
--TextColorHighlightBackground=555500
-+TextColorHighlightBackground=7a6f1c
- TextColorLink=textColorLink
- TextColorLinkVisited=textColorLinkVisited
- TextColorNormal=text
-@@ -143,7 +146,7 @@ OutputPanes_TestWarnTextColor=ffc8c800
- OutputPanes_TestFatalTextColor=ffb42828
- OutputPanes_TestDebugTextColor=ff329696
- OutputPaneButtonFlashColor=error
--OutputPaneToggleButtonTextColorChecked=text
-+OutputPaneToggleButtonTextColorChecked=textHighlighted
- OutputPaneToggleButtonTextColorUnchecked=text
-
- Debugger_LogWindow_LogInput=ff00acac
-@@ -203,10 +206,10 @@ PaletteBrightText=ffff0000
- PaletteText=text
- PaletteButtonText=text
- PaletteButtonTextDisabled=textDisabled
--PaletteToolTipBase=selectedBackground
--PaletteHighlight=selectedBackground
-+PaletteToolTipBase=66000000
-+PaletteHighlight=selectedBackgroundText
- PaletteDark=shadowBackground
--PaletteHighlightedText=ffffffff
-+PaletteHighlightedText=textHighlighted
- PaletteToolTipText=text
- PaletteLink=textColorLink
- PaletteLinkVisited=textColorLinkVisited
-diff --git a/share/qtcreator/themes/design.creatortheme b/share/qtcreator/themes/design.creatortheme
-index 8db109f313..cd90ad49de 100644
---- a/share/qtcreator/themes/design.creatortheme
-+++ b/share/qtcreator/themes/design.creatortheme
-@@ -17,6 +17,9 @@ text=ffdadada
- ;disabled text
- textDisabled=60a4a6a8
-
-+;background for selected text
-+selectedBackgroundText=aa1f75cc
-+
- ;icons, spinbox ticks,
- ;toolBarItem=b6fbfdff
- toolBarItem=ffb3b3b3
-@@ -50,7 +53,7 @@ hoverBackground=ff404244
- ;blended background color for controls 1 spinboxes, background selection square for snapping modes, publish as alias icon.
- ;color for filter background and overwrite width and height boxes
- ;selectedBackground=66000000
--selectedBackground=ff111111
-+selectedBackground=aa1f75cc
-
-
- ;background for default "open a document" screen in the edit mode,
-@@ -108,6 +111,7 @@ DoubleTabWidget2ndTabInactiveTextColor=text
- EditorPlaceholderColor=normalBackground
- FancyToolBarSeparatorColor=toolBarItemDisabled
- FancyTabBarBackgroundColor=shadowBackground
-+FancyTabBarSelectedBackgroundColor=ff000000
- FancyTabWidgetDisabledSelectedTextColor=toolBarItemDisabled
- FancyTabWidgetDisabledUnselectedTextColor=toolBarItemDisabled
- FancyTabWidgetEnabledSelectedTextColor=fancyBarsBoldTextColor
-@@ -378,7 +382,7 @@ PaletteToolTipBase=selectedBackground
-
-
- ;the selection highlight on the dropdown combo box in the file selection top menu and connections panel and tab mode selector dropdowns
--PaletteHighlight=selectedBackground
-+PaletteHighlight=selectedBackgroundText
- ;PaletteHighlight=ffd3299a
-
-
-diff --git a/share/qtcreator/themes/flat-dark.creatortheme b/share/qtcreator/themes/flat-dark.creatortheme
-index 0c01aa1707..e79a96056d 100644
---- a/share/qtcreator/themes/flat-dark.creatortheme
-+++ b/share/qtcreator/themes/flat-dark.creatortheme
-@@ -4,15 +4,17 @@ PreferredStyles=Fusion
- DefaultTextEditorColorScheme=creator-dark.xml
-
- [Palette]
--shadowBackground=ff404244
-+shadowBackground=ff404142
- text=ffd0d0d0
- textDisabled=60a4a6a8
--toolBarItem=b6fbfdff
--toolBarItemDisabled=60a4a6a8
-+textHighlighted=fff0f0f0
-+toolBarItem=bcfbfdff
-+toolBarItemDisabled=56a5a6a7
- fancyBarsNormalTextColor=ffd0d0d0
- fancyBarsBoldTextColor=b6fbfdff
--hoverBackground=22ffffff
--selectedBackground=66000000
-+hoverBackground=28ffffff
-+selectedBackground=7a000000
-+selectedBackgroundText=ff1d545c
- normalBackground=ff2E2F30
- alternateBackground=ff353637
- error=ffdf4f4f
-@@ -52,6 +54,7 @@ DoubleTabWidget2ndTabInactiveTextColor=text
- EditorPlaceholderColor=normalBackground
- FancyToolBarSeparatorColor=toolBarItemDisabled
- FancyTabBarBackgroundColor=shadowBackground
-+FancyTabBarSelectedBackgroundColor=selectedBackground
- FancyTabWidgetDisabledSelectedTextColor=toolBarItemDisabled
- FancyTabWidgetDisabledUnselectedTextColor=toolBarItemDisabled
- FancyTabWidgetEnabledSelectedTextColor=fancyBarsBoldTextColor
-@@ -122,7 +125,7 @@ SplitterColor=splitter
- TextColorDisabled=textDisabled
- TextColorError=ffff4040
- TextColorHighlight=ffff0000
--TextColorHighlightBackground=8a7f2c
-+TextColorHighlightBackground=7a6f1c
- TextColorLink=textColorLink
- TextColorLinkVisited=textColorLinkVisited
- TextColorNormal=text
-@@ -147,7 +150,7 @@ OutputPanes_TestWarnTextColor=ffc8c800
- OutputPanes_TestFatalTextColor=ffc82828
- OutputPanes_TestDebugTextColor=ff329696
- OutputPaneButtonFlashColor=error
--OutputPaneToggleButtonTextColorChecked=fancyBarsNormalTextColor
-+OutputPaneToggleButtonTextColorChecked=textHighlighted
- OutputPaneToggleButtonTextColorUnchecked=fancyBarsNormalTextColor
-
- Debugger_LogWindow_LogInput=ff00acac
-@@ -221,10 +224,10 @@ PaletteBrightText=ffff3333
- PaletteText=text
- PaletteButtonText=text
- PaletteButtonTextDisabled=textDisabled
--PaletteToolTipBase=selectedBackground
--PaletteHighlight=selectedBackground
-+PaletteToolTipBase=darkBackground
-+PaletteHighlight=selectedBackgroundText
- PaletteDark=shadowBackground
--PaletteHighlightedText=ffffffff
-+PaletteHighlightedText=textHighlighted
- PaletteToolTipText=text
- PaletteLink=textColorLink
- PaletteLinkVisited=textColorLinkVisited
-diff --git a/share/qtcreator/themes/flat-light.creatortheme b/share/qtcreator/themes/flat-light.creatortheme
-index 29edca63fd..f6b726762c 100644
---- a/share/qtcreator/themes/flat-light.creatortheme
-+++ b/share/qtcreator/themes/flat-light.creatortheme
-@@ -50,6 +50,7 @@ DoubleTabWidget2ndTabInactiveTextColor=ff000000
- EditorPlaceholderColor=fff4f4f4
- FancyToolBarSeparatorColor=toolBarItemDisabled
- FancyTabBarBackgroundColor=shadowBackground
-+FancyTabBarSelectedBackgroundColor=selectedBackground
- FancyTabWidgetDisabledSelectedTextColor=toolBarItemDisabled
- FancyTabWidgetDisabledUnselectedTextColor=toolBarItemDisabled
- FancyTabWidgetEnabledSelectedTextColor=fancyBarsBoldTextColor
-diff --git a/share/qtcreator/themes/flat.creatortheme b/share/qtcreator/themes/flat.creatortheme
-index ab0189528f..0f057d80c0 100644
---- a/share/qtcreator/themes/flat.creatortheme
-+++ b/share/qtcreator/themes/flat.creatortheme
-@@ -3,15 +3,15 @@ ThemeName=Flat
- PreferredStyles=
-
- [Palette]
--shadowBackground=ff404244
-+shadowBackground=ff404142
- text=ff000000
- textDisabled=55000000
--toolBarItem=b6fbfdff
--toolBarItemDisabled=60a4a6a8
-+toolBarItem=bcfbfdff
-+toolBarItemDisabled=56a5a6a7
- fancyBarsNormalTextColor=ffffffff
- fancyBarsBoldTextColor=b6fbfdff
--hoverBackground=22ffffff
--selectedBackground=66000000
-+hoverBackground=28ffffff
-+selectedBackground=7a000000
- normalBackground=ffffffff
- alternateBackground=ff515151
- error=ffdf4f4f
-@@ -48,6 +48,7 @@ DoubleTabWidget2ndTabInactiveTextColor=ff000000
- EditorPlaceholderColor=ffdddddd
- FancyToolBarSeparatorColor=toolBarItemDisabled
- FancyTabBarBackgroundColor=shadowBackground
-+FancyTabBarSelectedBackgroundColor=selectedBackground
- FancyTabWidgetDisabledSelectedTextColor=toolBarItemDisabled
- FancyTabWidgetDisabledUnselectedTextColor=toolBarItemDisabled
- FancyTabWidgetEnabledSelectedTextColor=fancyBarsBoldTextColor
-diff --git a/src/libs/utils/icon.cpp b/src/libs/utils/icon.cpp
-index dc7625aae3..f7edbd8614 100644
---- a/src/libs/utils/icon.cpp
-+++ b/src/libs/utils/icon.cpp
-@@ -139,13 +139,13 @@ static QPixmap masksToIcon(const MasksAndColors &masks, const QPixmap &combinedM
- if (style & Icon::DropShadow && creatorTheme()->flag(Theme::ToolBarIconShadow)) {
- const QPixmap shadowMask = maskToColorAndAlpha(combinedMask, Qt::black);
- p.setCompositionMode(QPainter::CompositionMode_DestinationOver);
-- p.setOpacity(0.05);
-+ p.setOpacity(0.08);
- p.drawPixmap(QPointF(0, -0.501), shadowMask);
- p.drawPixmap(QPointF(-0.501, 0), shadowMask);
- p.drawPixmap(QPointF(0.5, 0), shadowMask);
- p.drawPixmap(QPointF(0.5, 0.5), shadowMask);
- p.drawPixmap(QPointF(-0.501, 0.5), shadowMask);
-- p.setOpacity(0.2);
-+ p.setOpacity(0.3);
- p.drawPixmap(0, 1, shadowMask);
- }
-
-diff --git a/src/libs/utils/theme/theme.h b/src/libs/utils/theme/theme.h
-index 9a881e9e64..f350bf0ca2 100644
---- a/src/libs/utils/theme/theme.h
-+++ b/src/libs/utils/theme/theme.h
-@@ -80,6 +80,7 @@ public:
- EditorPlaceholderColor,
- FancyToolBarSeparatorColor,
- FancyTabBarBackgroundColor,
-+ FancyTabBarSelectedBackgroundColor,
- FancyTabWidgetDisabledSelectedTextColor,
- FancyTabWidgetDisabledUnselectedTextColor,
- FancyTabWidgetEnabledSelectedTextColor,
-diff --git a/src/plugins/coreplugin/fancytabwidget.cpp b/src/plugins/coreplugin/fancytabwidget.cpp
-index 4fad26bc12..3df5112be2 100644
---- a/src/plugins/coreplugin/fancytabwidget.cpp
-+++ b/src/plugins/coreplugin/fancytabwidget.cpp
-@@ -288,6 +288,13 @@ static void paintIcon(QPainter *painter, const QRect &rect,
- if (!enabled && !creatorTheme()->flag(Theme::FlatToolBars))
- painter->setOpacity(0.7);
- StyleHelper::drawIconWithShadow(icon, iconRect, painter, iconMode);
-+
-+ if (selected && creatorTheme()->flag(Theme::FlatToolBars)) {
-+ painter->setOpacity(1.0);
-+ QRect accentRect = rect;
-+ accentRect.setWidth(2);
-+ painter->fillRect(accentRect, creatorTheme()->color(Theme::IconsBaseColor));
-+ }
- }
-
- static void paintIconAndText(QPainter *painter, const QRect &rect,
-@@ -315,6 +322,11 @@ static void paintIconAndText(QPainter *painter, const QRect &rect,
- }
-
- painter->setOpacity(1.0); //FIXME: was 0.7 before?
-+ if (selected && creatorTheme()->flag(Theme::FlatToolBars)) {
-+ QRect accentRect = rect;
-+ accentRect.setWidth(2);
-+ painter->fillRect(accentRect, creatorTheme()->color(Theme::IconsBaseColor));
-+ }
- if (enabled) {
- painter->setPen(
- selected ? creatorTheme()->color(Theme::FancyTabWidgetEnabledSelectedTextColor)
-@@ -349,7 +361,7 @@ void FancyTabBar::paintTab(QPainter *painter, int tabIndex) const
- if (selected) {
- if (creatorTheme()->flag(Theme::FlatToolBars)) {
- // background color of a fancy tab that is active
-- painter->fillRect(rect, creatorTheme()->color(Theme::FancyToolButtonSelectedColor));
-+ painter->fillRect(rect, creatorTheme()->color(Theme::FancyTabBarSelectedBackgroundColor));
- } else {
- paintSelectedTabBackground(painter, rect);
- }
-diff --git a/src/plugins/coreplugin/locator/locatorwidget.cpp b/src/plugins/coreplugin/locator/locatorwidget.cpp
-index 7276685d20..2421bd776a 100644
---- a/src/plugins/coreplugin/locator/locatorwidget.cpp
-+++ b/src/plugins/coreplugin/locator/locatorwidget.cpp
-@@ -87,6 +87,7 @@ public:
- LocatorModel(QObject *parent = nullptr)
- : QAbstractListModel(parent)
- , mBackgroundColor(Utils::creatorTheme()->color(Utils::Theme::TextColorHighlightBackground))
-+ , mForegroundColor(Utils::creatorTheme()->color(Utils::Theme::TextColorNormal))
- {}
-
- void clear();
-@@ -100,6 +101,7 @@ private:
- mutable QList<LocatorFilterEntry> mEntries;
- bool hasExtraInfo = false;
- QColor mBackgroundColor;
-+ QColor mForegroundColor;
- };
-
- class CompletionDelegate : public HighlightingItemDelegate
-@@ -224,6 +226,8 @@ QVariant LocatorModel::data(const QModelIndex &index, int role) const
- }
- case int(HighlightingItemRole::Background):
- return mBackgroundColor;
-+ case int(HighlightingItemRole::Foreground):
-+ return mForegroundColor;
- }
-
- return QVariant();