aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/libs/utils/CMakeLists.txt1
-rw-r--r--src/libs/utils/aspects.cpp2
-rw-r--r--src/libs/utils/buildablehelperlibrary.cpp18
-rw-r--r--src/libs/utils/buildablehelperlibrary.h1
-rw-r--r--src/libs/utils/datafromprocess.h59
-rw-r--r--src/libs/utils/layoutbuilder.cpp5
-rw-r--r--src/libs/utils/layoutbuilder.h1
-rw-r--r--src/libs/utils/qtcwidgets.cpp39
-rw-r--r--src/libs/utils/qtcwidgets.h1
-rw-r--r--src/libs/utils/qtdesignsystemstyle.cpp157
-rw-r--r--src/libs/utils/qtdesignsystemstyle.h31
-rw-r--r--src/libs/utils/settingsdatabase.cpp27
-rw-r--r--src/libs/utils/utils.qbs2
-rw-r--r--src/plugins/clangtools/executableinfo.cpp26
-rw-r--r--src/plugins/clangtools/executableinfo.h6
-rw-r--r--src/plugins/cmakeprojectmanager/cmakesettingspage.cpp4
-rw-r--r--src/plugins/coreplugin/locator/locator.cpp143
-rw-r--r--src/plugins/coreplugin/locator/locator.h33
-rw-r--r--src/plugins/coreplugin/locator/locatormanager.cpp2
-rw-r--r--src/plugins/coreplugin/locator/locatorsettingspage.cpp33
-rw-r--r--src/plugins/coreplugin/locator/locatorwidget.cpp24
-rw-r--r--src/plugins/debugger/debuggeritemmanager.cpp23
-rw-r--r--src/plugins/projectexplorer/buildsteplist.cpp7
-rw-r--r--src/plugins/projectexplorer/buildsteplist.h1
-rw-r--r--src/plugins/projectexplorer/devicesupport/idevice.cpp5
-rw-r--r--src/plugins/projectexplorer/devicesupport/idevice.h1
-rw-r--r--src/plugins/projectexplorer/gcctoolchain.cpp52
-rw-r--r--src/plugins/projectexplorer/msvctoolchain.cpp14
-rw-r--r--src/plugins/projectexplorer/toolchain.h2
-rw-r--r--src/plugins/projectexplorer/toolchainmanager.cpp6
-rw-r--r--src/plugins/projectexplorer/toolchainoptionspage.cpp15
-rw-r--r--src/plugins/python/pythonsettings.cpp147
-rw-r--r--src/plugins/qmakeprojectmanager/qmakebuildconfiguration.cpp10
-rw-r--r--src/plugins/qmakeprojectmanager/qmakebuildconfiguration.h6
-rw-r--r--src/plugins/qmakeprojectmanager/qmakeproject.cpp10
-rw-r--r--src/plugins/qtsupport/qtoptionspage.cpp3
-rw-r--r--src/plugins/qtsupport/qtsupportconstants.h2
-rw-r--r--src/plugins/qtsupport/qtsupportplugin.cpp20
-rw-r--r--src/plugins/qtsupport/qtversionmanager.cpp17
-rw-r--r--src/plugins/saferenderer/saferenderer.qrc7
-rw-r--r--src/plugins/saferenderer/wizards/qsrapp2_1/CMakeLists.txt5
-rw-r--r--src/plugins/saferenderer/wizards/qsrapp2_1/main.cpp.tpl7
-rw-r--r--src/plugins/saferenderer/wizards/qsrapp2_1/wizard.json2
-rw-r--r--src/plugins/saferenderer/wizards/qsrapp2_2/CMakeLists.txt72
-rw-r--r--src/plugins/saferenderer/wizards/qsrapp2_2/file.pro46
-rw-r--r--src/plugins/saferenderer/wizards/qsrapp2_2/main.cpp.tpl59
-rw-r--r--src/plugins/saferenderer/wizards/qsrapp2_2/main.qml.tpl25
-rw-r--r--src/plugins/saferenderer/wizards/qsrapp2_2/qml.qrc.tpl5
-rw-r--r--src/plugins/saferenderer/wizards/qsrapp2_2/safeasset.qrc.tpl2
-rw-r--r--src/plugins/saferenderer/wizards/qsrapp2_2/wizard.json115
-rw-r--r--tests/manual/widgets/components/tst_manual_widgets_components.cpp5
51 files changed, 949 insertions, 357 deletions
diff --git a/src/libs/utils/CMakeLists.txt b/src/libs/utils/CMakeLists.txt
index a7e6ed78eac..9fcb8a4edfe 100644
--- a/src/libs/utils/CMakeLists.txt
+++ b/src/libs/utils/CMakeLists.txt
@@ -147,6 +147,7 @@ add_qtc_library(Utils
qtcprocess.cpp qtcprocess.h
qtcsettings.cpp qtcsettings.h qtcsettings_p.h
qtcwidgets.cpp qtcwidgets.h
+ qtdesignsystemstyle.cpp qtdesignsystemstyle.h
ranges.h
reloadpromptutils.cpp reloadpromptutils.h
removefiledialog.cpp removefiledialog.h
diff --git a/src/libs/utils/aspects.cpp b/src/libs/utils/aspects.cpp
index cd8ed27089b..c9c519622c1 100644
--- a/src/libs/utils/aspects.cpp
+++ b/src/libs/utils/aspects.cpp
@@ -449,7 +449,7 @@ bool BaseAspect::isAutoApply() const
}
/*!
- Sets auto-apply mode. When auto-apply mode is \a on, user interaction to this
+ Sets auto-apply mode. When auto-apply mode is \a off, user interaction to this
aspect's widget will not modify the \c value of the aspect until \c apply()
is called programmatically.
diff --git a/src/libs/utils/buildablehelperlibrary.cpp b/src/libs/utils/buildablehelperlibrary.cpp
index fdf7d23121a..a34811e97c4 100644
--- a/src/libs/utils/buildablehelperlibrary.cpp
+++ b/src/libs/utils/buildablehelperlibrary.cpp
@@ -99,16 +99,22 @@ static FilePaths findQmakesInDir(const FilePath &dir)
FilePaths BuildableHelperLibrary::findQtsInEnvironment(
const Environment &env, const FilePath &deviceRoot)
{
- FilePaths qmakeList;
- std::set<FilePath> canonicalEnvPaths;
- const FilePaths paths = env.path();
- for (const FilePath &path : paths) {
+ return findQtsInPaths(Utils::transform(env.path(), [&deviceRoot](const FilePath &path) {
FilePath devPath = deviceRoot.withNewMappedPath(path);
if (QTC_UNEXPECTED(deviceRoot.isEmpty()))
devPath = path;
- if (!canonicalEnvPaths.insert(devPath.canonicalPath()).second)
+ return devPath;
+ }));
+}
+
+FilePaths BuildableHelperLibrary::findQtsInPaths(const FilePaths &paths)
+{
+ FilePaths qmakeList;
+ std::set<FilePath> canonicalEnvPaths;
+ for (const FilePath &path : paths) {
+ if (!canonicalEnvPaths.insert(path.canonicalPath()).second)
continue;
- qmakeList << findQmakesInDir(devPath);
+ qmakeList << findQmakesInDir(path);
}
return qmakeList;
}
diff --git a/src/libs/utils/buildablehelperlibrary.h b/src/libs/utils/buildablehelperlibrary.h
index a8de770b76e..ee735504708 100644
--- a/src/libs/utils/buildablehelperlibrary.h
+++ b/src/libs/utils/buildablehelperlibrary.h
@@ -17,6 +17,7 @@ class QTCREATOR_UTILS_EXPORT BuildableHelperLibrary
{
public:
static FilePaths findQtsInEnvironment(const Environment &env, const FilePath &deviceRoot);
+ static FilePaths findQtsInPaths(const FilePaths &paths);
static bool isQtChooser(const FilePath &filePath);
static FilePath qtChooserToQmakePath(const FilePath &path);
// return true if the qmake at qmakePath is a Qt (used by QtVersion)
diff --git a/src/libs/utils/datafromprocess.h b/src/libs/utils/datafromprocess.h
index e8b996b29aa..b87b7f7d133 100644
--- a/src/libs/utils/datafromprocess.h
+++ b/src/libs/utils/datafromprocess.h
@@ -8,9 +8,12 @@
#include "environment.h"
#include "filepath.h"
#include "qtcprocess.h"
+#include "settingsdatabase.h"
#include <QDateTime>
#include <QHash>
+#include <QJsonDocument>
+#include <QJsonObject>
#include <QMutex>
#include <QMutexLocker>
@@ -47,6 +50,8 @@ public:
OutputParser parser;
ErrorHandler errorHandler;
Callback callback;
+ Callback cachedValueChangedCallback;
+ bool persistValue = true;
QList<ProcessResult> allowedResults{ProcessResult::FinishedWithSuccess};
};
@@ -104,6 +109,33 @@ inline std::optional<Data> DataFromProcess<Data>::getOrProvideData(const Paramet
const auto outputRetriever = std::make_shared<Process>();
outputRetriever->setCommand(params.commandLine);
+
+ if (params.persistValue && !params.callback) {
+ const QChar separator = params.commandLine.executable().pathListSeparator();
+ const QString stringKey = params.commandLine.executable().toUrlishString() + separator
+ + params.commandLine.arguments() + separator
+ + params.environment.toStringList().join(separator);
+ if (const QByteArray json = SettingsDatabase::value(stringKey).toByteArray();
+ !json.isEmpty()) {
+ if (const auto doc = QJsonDocument::fromJson(json); doc.isObject()) {
+ const QJsonObject settingsObject = doc.object();
+ const QString out = settingsObject["stdout"].toString();
+ const QString err = settingsObject["stderr"].toString();
+ std::optional<Data> data = params.parser(out, err);
+ QMutexLocker<QMutex> cacheLocker(&m_cacheMutex);
+ m_cache.insert(key, std::make_pair(data, exeTimestamp));
+ QObject::connect(
+ outputRetriever.get(),
+ &Process::done,
+ [params, exeTimestamp, key, outputRetriever] {
+ handleProcessFinished(params, exeTimestamp, key, outputRetriever);
+ });
+ outputRetriever->start();
+ return data;
+ }
+ }
+ }
+
if (params.callback) {
QObject::connect(outputRetriever.get(),
&Process::done,
@@ -133,11 +165,34 @@ inline std::optional<Data> DataFromProcess<Data>::handleProcessFinished(
}
std::optional<Data> data;
- if (params.allowedResults.contains(process->result()))
+ if (params.allowedResults.contains(process->result())) {
+ if (params.persistValue) {
+ const QChar separator = params.commandLine.executable().pathListSeparator();
+ const QString stringKey = params.commandLine.executable().toUrlishString() + separator
+ + params.commandLine.arguments() + separator
+ + params.environment.toStringList().join(separator);
+ QJsonObject settingsObject;
+ const QString out = process->cleanedStdOut();
+ const QString err = process->cleanedStdErr();
+ settingsObject["stdout"] = out;
+ settingsObject["stderr"] = err;
+ SettingsDatabase::setValue(
+ stringKey,
+ QString::fromUtf8(QJsonDocument(settingsObject).toJson(QJsonDocument::Compact)));
+ }
data = params.parser(process->cleanedStdOut(), process->cleanedStdErr());
- else if (params.errorHandler)
+ } else if (params.errorHandler) {
params.errorHandler(*process);
+ }
QMutexLocker<QMutex> cacheLocker(&m_cacheMutex);
+ if (params.cachedValueChangedCallback) {
+ const auto it = m_cache.constFind(cacheKey);
+ if (it != m_cache.constEnd() && it.value().second == exeTimestamp) {
+ if (it.value().first != data)
+ params.cachedValueChangedCallback(data);
+ }
+ }
+
m_cache.insert(cacheKey, std::make_pair(data, exeTimestamp));
if (params.callback) {
params.callback(data);
diff --git a/src/libs/utils/layoutbuilder.cpp b/src/libs/utils/layoutbuilder.cpp
index 992e3409355..95f965d392d 100644
--- a/src/libs/utils/layoutbuilder.cpp
+++ b/src/libs/utils/layoutbuilder.cpp
@@ -522,6 +522,11 @@ void addToLayout(Layout *layout, QWidget *inner)
layout->addLayoutItem(inner);
}
+void addToLayout(Layout *layout, QWidget &inner)
+{
+ layout->addLayoutItem(&inner);
+}
+
void addToLayout(Layout *layout, QLayout *inner)
{
layout->addLayoutItem(inner);
diff --git a/src/libs/utils/layoutbuilder.h b/src/libs/utils/layoutbuilder.h
index 3c6b9925a3b..fb5e8813151 100644
--- a/src/libs/utils/layoutbuilder.h
+++ b/src/libs/utils/layoutbuilder.h
@@ -703,6 +703,7 @@ QTC_DEFINE_BUILDER_SETTER(minimumHeight, setMinimumHeight)
QTCREATOR_UTILS_EXPORT void addToLayout(Layout *layout, const Layout &inner);
QTCREATOR_UTILS_EXPORT void addToLayout(Layout *layout, const Widget &inner);
QTCREATOR_UTILS_EXPORT void addToLayout(Layout *layout, QWidget *inner);
+QTCREATOR_UTILS_EXPORT void addToLayout(Layout *layout, QWidget &inner);
QTCREATOR_UTILS_EXPORT void addToLayout(Layout *layout, QLayout *inner);
QTCREATOR_UTILS_EXPORT void addToLayout(Layout *layout, const LayoutModifier &inner);
QTCREATOR_UTILS_EXPORT void addToLayout(Layout *layout, const QString &inner);
diff --git a/src/libs/utils/qtcwidgets.cpp b/src/libs/utils/qtcwidgets.cpp
index 84e8c9c41c5..9f7cf62dcc1 100644
--- a/src/libs/utils/qtcwidgets.cpp
+++ b/src/libs/utils/qtcwidgets.cpp
@@ -6,6 +6,7 @@
#include "hostosinfo.h"
#include "icon.h"
#include "networkaccessmanager.h"
+#include "qtdesignsystemstyle.h"
#include <QtTaskTree/QNetworkReplyWrapper>
#include <QtTaskTree/QSingleTaskTreeRunner>
@@ -896,49 +897,13 @@ void QtcImage::setPixmap(const QPixmap &px)
update();
}
-constexpr TextFormat TabBarTf
- {Theme::Token_Text_Muted, StyleHelper::UiElementH5};
-constexpr TextFormat TabBarTfActive
- {Theme::Token_Text_Default, TabBarTf.uiElement};
-
QtcTabBar::QtcTabBar(QWidget *parent)
: QTabBar(parent)
{
- setExpanding(false);
- setFont(TabBarTf.font());
+ setStyle(QtDesignSystemStyle::instance());
setMouseTracking(true);
}
-void QtcTabBar::paintEvent([[maybe_unused]] QPaintEvent *event)
-{
- QPainter p(this);
- const int padding = PaddingHXxs;
- const QRectF borderR = rect().toRectF().adjusted(padding + 0.5, 0.5, -(padding + 0.5), -0.5);
- p.setPen(creatorColor(isEnabled() ? Theme::Token_Stroke_Subtle
- : Theme::Token_Foreground_Subtle));
- p.drawLine(borderR.bottomLeft(), borderR.bottomRight());
- p.setFont(TabBarTf.font());
- for (int tabIndex = 0; tabIndex < count(); tabIndex++) {
- QStyleOptionTab opt;
- initStyleOption(&opt, tabIndex);
- const bool selected = opt.state & QStyle::State_Selected;
- const bool enabled = isEnabled();
- const bool hovered = !selected && opt.rect.contains(mapFromGlobal(QCursor::pos()));
- if (selected || (hovered && enabled)) {
- QRect highLightRect = opt.rect.adjusted(padding, 0, -padding, 0);
- highLightRect.moveTop(highLightRect.height() - StyleHelper::HighlightThickness);
- const QColor color = creatorColor(enabled ? hovered ? Theme::Token_Text_Subtle
- : Theme::Token_Accent_Default
- : Theme::Token_Foreground_Subtle);
- p.fillRect(highLightRect, color);
- }
- const QColor textColor = enabled ? (selected ? TabBarTfActive : TabBarTf).color()
- : creatorColor(Theme::Token_Text_Subtle);
- p.setPen(textColor);
- p.drawText(opt.rect, Qt::AlignCenter, opt.text);
- }
-}
-
bool QtcTabBar::event(QEvent *event)
{
if (event->type() == QEvent::MouseMove || event->type() == QEvent::Leave)
diff --git a/src/libs/utils/qtcwidgets.h b/src/libs/utils/qtcwidgets.h
index 52c3bb25ae4..7e07b93e7a4 100644
--- a/src/libs/utils/qtcwidgets.h
+++ b/src/libs/utils/qtcwidgets.h
@@ -177,7 +177,6 @@ public:
QtcTabBar(QWidget *parent = nullptr);
protected:
- void paintEvent(QPaintEvent *event) override;
bool event(QEvent *event) override;
};
diff --git a/src/libs/utils/qtdesignsystemstyle.cpp b/src/libs/utils/qtdesignsystemstyle.cpp
new file mode 100644
index 00000000000..1eebe93a297
--- /dev/null
+++ b/src/libs/utils/qtdesignsystemstyle.cpp
@@ -0,0 +1,157 @@
+// Copyright (C) 2025 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#include "qtdesignsystemstyle.h"
+
+#include "stylehelper.h"
+#include "utilsicons.h"
+
+#include <QGuiApplication>
+#include <QPaintEvent>
+#include <QPainter>
+#include <QPainterPath>
+#include <QPixmapCache>
+#include <QWidget>
+#include <QStyleOption>
+#include <QTabBar>
+
+namespace Utils {
+
+using namespace StyleHelper;
+using namespace StyleHelper::SpacingTokens;
+
+constexpr TextFormat TabBarTf
+ {Theme::Token_Text_Muted, StyleHelper::UiElementH5};
+constexpr TextFormat TabBarTfActive
+ {Theme::Token_Text_Default, TabBarTf.uiElement};
+constexpr TextFormat TabBarTfDisabled
+ {Theme::Token_Text_Subtle, TabBarTf.uiElement};
+
+QtDesignSystemStyle::QtDesignSystemStyle()
+{
+}
+
+QtDesignSystemStyle::~QtDesignSystemStyle() = default;
+
+void QtDesignSystemStyle::drawControl(ControlElement element, const QStyleOption *opt,
+ QPainter *painter, const QWidget *widget) const
+{
+ switch (element) {
+ case CE_TabBarTabLabel: {
+ auto tabOpt = qstyleoption_cast<const QStyleOptionTab*>(opt);
+ QStyleOptionTab myTabOpt = *tabOpt;
+ const QColor c = ((myTabOpt.state & QStyle::State_Enabled) ?
+ (myTabOpt.state & QStyle::State_Selected) ? TabBarTfActive
+ : TabBarTf
+ : TabBarTfDisabled).color();
+ myTabOpt.palette.setColor(widget->foregroundRole(), c);
+ myTabOpt.state = myTabOpt.state & ~QStyle::State_HasFocus; // Avoid extra focus rect
+ QCommonStyle::drawControl(element, &myTabOpt, painter, widget);
+ break;
+ }
+ case CE_TabBarTabShape: {
+ const bool selected = opt->state & QStyle::State_Selected;
+ const bool enabled = opt->state & QStyle::State_Enabled;
+ const bool hovered = !selected && opt->rect.contains(widget->mapFromGlobal(QCursor::pos()));
+ auto tabOpt = qstyleoption_cast<const QStyleOptionTab*>(opt);
+ const int paddingL = tabOpt->position == QStyleOptionTab::Beginning ? 0 : PaddingHXxs;
+ const int paddingR = tabOpt->position == QStyleOptionTab::End ? 0 : PaddingHXxs;
+ const QRect shapeR = opt->rect.adjusted(paddingL, 0, -paddingR, 0);
+ if (selected || (hovered && enabled)) {
+ if (hovered || tabOpt->position == QStyleOptionTab::Moving) {
+ StyleHelper::drawCardBg(painter, shapeR.adjusted(0, 0, 0, +SpacingTokens::RadiusS),
+ creatorColor(Theme::Token_Foreground_Subtle));
+ }
+ QRect highLightRect = shapeR;
+ highLightRect.moveTop(highLightRect.height() - StyleHelper::HighlightThickness);
+ const QColor color = creatorColor(enabled ? hovered ? Theme::Token_Text_Subtle
+ : Theme::Token_Accent_Default
+ : Theme::Token_Foreground_Subtle);
+ painter->fillRect(highLightRect, color);
+ }
+ break;
+ }
+ default:
+ QCommonStyle::drawControl(element, opt, painter, widget);
+ break;
+ }
+}
+
+void QtDesignSystemStyle::drawPrimitive(PrimitiveElement element, const QStyleOption *opt,
+ QPainter *painter, const QWidget *widget) const
+{
+ switch (element) {
+ case PE_FrameTabBarBase: {
+ QRectF borderR = opt->rect.toRectF();
+ const int lineWidth = 1;
+ borderR.setTop(borderR.bottom() - lineWidth);
+ const bool enabled = opt->state & QStyle::State_Enabled;
+ const QColor color = creatorColor(enabled ? Theme::Token_Stroke_Subtle
+ : Theme::Token_Foreground_Subtle);
+ painter->fillRect(borderR, color);
+ break;
+ }
+ default:
+ QCommonStyle::drawPrimitive(element, opt, painter, widget);
+ break;
+ }
+}
+
+int QtDesignSystemStyle::pixelMetric(PixelMetric m, const QStyleOption *opt,
+ const QWidget *widget) const
+{
+ switch (m) {
+ case PM_TabBarTabShiftVertical:
+ case PM_TabBarTabShiftHorizontal:
+ return 0;
+ case PM_TabBarTabHSpace:
+ return PaddingHL + PaddingHL;
+ case PM_TabBarTabVSpace: {
+ const int textHeight = opt->fontMetrics.height();
+ return PaddingVM + TabBarTf.lineHeight() + PaddingVM - textHeight;
+ }
+ default:
+ return QCommonStyle::pixelMetric(m, opt, widget);
+ }
+}
+
+QIcon QtDesignSystemStyle::standardIcon(StandardPixmap sp, const QStyleOption *opt,
+ const QWidget *widget) const
+{
+ QIcon icon;
+
+ switch (sp) {
+ case SP_TabCloseButton: {
+ static const QIcon tabClose = Icons::CLOSE_FOREGROUND.icon();
+ icon = tabClose;
+ break;
+ }
+ default:
+ icon = QCommonStyle::standardIcon(sp, opt, widget);
+ break;
+ }
+
+ return icon;
+}
+void QtDesignSystemStyle::polish(QWidget *widget)
+{
+ QCommonStyle::polish(widget);
+
+ if (auto tabBar = qobject_cast<QTabBar*>(widget)) {
+ tabBar->setFont(TabBarTf.font());
+ for (int count = tabBar->count(), i = 0; i < count; ++i ) {
+ for (const QTabBar::ButtonPosition pos : {QTabBar::LeftSide, QTabBar::RightSide}) {
+ if (QWidget *tabButton = tabBar->tabButton(i, pos))
+ tabButton->setStyle(this);
+ }
+ }
+ }
+}
+
+QStyle *QtDesignSystemStyle::instance()
+{
+ static QtDesignSystemStyle style;
+ return &style;
+}
+
+} // namespace Utils
diff --git a/src/libs/utils/qtdesignsystemstyle.h b/src/libs/utils/qtdesignsystemstyle.h
new file mode 100644
index 00000000000..ed69ca53fe9
--- /dev/null
+++ b/src/libs/utils/qtdesignsystemstyle.h
@@ -0,0 +1,31 @@
+// Copyright (C) 2025 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#pragma once
+
+#include "utils_global.h"
+
+#include <QCommonStyle>
+
+namespace Utils {
+
+class QTCREATOR_UTILS_EXPORT QtDesignSystemStyle : public QCommonStyle
+{
+public:
+ QtDesignSystemStyle();
+ ~QtDesignSystemStyle();
+
+ void drawControl(ControlElement element, const QStyleOption *opt, QPainter *painter,
+ const QWidget *widget = nullptr) const override;
+ void drawPrimitive(PrimitiveElement element, const QStyleOption *opt, QPainter *painter,
+ const QWidget *widget = nullptr) const override;
+ int pixelMetric(PixelMetric metric, const QStyleOption *opt = nullptr,
+ const QWidget *widget = nullptr) const override;
+ QIcon standardIcon(StandardPixmap sp, const QStyleOption *opt,
+ const QWidget *widget) const override;
+ void polish(QWidget *widget) override;
+
+ static QStyle *instance();
+};
+
+} // namespace Utils
diff --git a/src/libs/utils/settingsdatabase.cpp b/src/libs/utils/settingsdatabase.cpp
index c4e862978d8..f53c81b2b8a 100644
--- a/src/libs/utils/settingsdatabase.cpp
+++ b/src/libs/utils/settingsdatabase.cpp
@@ -16,6 +16,8 @@
#include <QStringList>
#include <QVariant>
+#include <chrono>
+
/*!
\namespace Utils::SettingsDatabase
\inheaderfile utils/settingsdatabase.h
@@ -39,6 +41,7 @@ namespace Utils::SettingsDatabase {
enum { debug_settings = 0 };
using SettingsMap = QMap<QString, QVariant>;
+using LastUsageMap = QMap<QString, std::chrono::system_clock::time_point>;
class SettingsDatabaseImpl
{
@@ -58,6 +61,7 @@ public:
}
SettingsMap m_settings;
+ LastUsageMap m_lastUsage;
QStringList m_groups;
@@ -110,6 +114,17 @@ void ensureImpl()
}
}
+ QVariantMap lastUsages = value("SettingsDataBaseLastUsages").toMap();
+ for (auto it = d->m_settings.begin(); it != d->m_settings.constEnd(); ++it) {
+ auto lastUsageIt = lastUsages.find(it.key());
+ std::chrono::system_clock::time_point lastUsage;
+ if (lastUsageIt != lastUsages.end())
+ lastUsage = std::chrono::system_clock::from_time_t(lastUsageIt.value().toLongLong());
+ else
+ lastUsage = std::chrono::system_clock::now();
+ d->m_lastUsage.insert(it.key(), lastUsage);
+ }
+
// syncing can be slow, especially on Linux and Windows
d->m_db.exec(QLatin1String("PRAGMA synchronous = OFF;"));
}
@@ -122,6 +137,16 @@ void destroy()
// TODO: Delay writing of dirty keys and save them here
+ QVariantMap lastUsages;
+ const std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
+ for (auto it = d->m_lastUsage.begin(); it != d->m_lastUsage.end(); ++it) {
+ if (now - it.value() > std::chrono::months(1))
+ remove(it.key());
+ else
+ lastUsages.insert(it.key(), static_cast<qint64>(std::chrono::system_clock::to_time_t(it.value())));
+ }
+ setValue("SettingsDataBaseLastUsages", lastUsages);
+
delete d;
d = nullptr;
QSqlDatabase::removeDatabase(QLatin1String("settings"));
@@ -134,6 +159,7 @@ void setValue(const QString &key, const QVariant &value)
// Add to cache
d->m_settings.insert(effectiveKey, value);
+ d->m_lastUsage.insert(effectiveKey, std::chrono::system_clock::now());
if (!d->m_db.isOpen())
return;
@@ -175,6 +201,7 @@ QVariant value(const QString &key, const QVariant &defaultValue)
d->m_settings.insert(effectiveKey, value);
}
+ d->m_lastUsage.insert(effectiveKey, std::chrono::system_clock::now());
return value;
}
diff --git a/src/libs/utils/utils.qbs b/src/libs/utils/utils.qbs
index b7a5457c01a..1a9c9d24db1 100644
--- a/src/libs/utils/utils.qbs
+++ b/src/libs/utils/utils.qbs
@@ -278,6 +278,8 @@ QtcLibrary {
"qtcsettings_p.h",
"qtcwidgets.cpp",
"qtcwidgets.h",
+ "qtdesignsystemstyle.cpp",
+ "qtdesignsystemstyle.h",
"ranges.h",
"reloadpromptutils.cpp",
"reloadpromptutils.h",
diff --git a/src/plugins/clangtools/executableinfo.cpp b/src/plugins/clangtools/executableinfo.cpp
index 9a93d4dd79c..73f9e9f6ed8 100644
--- a/src/plugins/clangtools/executableinfo.cpp
+++ b/src/plugins/clangtools/executableinfo.cpp
@@ -175,6 +175,7 @@ static FilePath queryResourceDir(const FilePath &clangToolPath)
parser);
params.environment.setupEnglishOutput();
params.allowedResults << ProcessResult::FinishedWithError;
+ params.persistValue = false;
if (const auto filePath = DataFromProcess<FilePath>::getData(params))
return *filePath;
return {};
@@ -197,6 +198,7 @@ QString queryVersion(const FilePath &clangToolPath, QueryFailMode failMode)
return {};
};
DataFromProcess<QString>::Parameters params({clangToolPath, {"--version"}}, parser);
+ params.persistValue = true;
params.environment.setupEnglishOutput();
if (failMode == QueryFailMode::Noisy)
params.errorHandler = handleProcessError;
@@ -225,5 +227,29 @@ QPair<FilePath, QString> getClangIncludeDirAndVersion(const FilePath &clangToolP
return it.value();
}
+bool operator==(const ClazyStandaloneInfo &c1, const ClazyStandaloneInfo &c2)
+{
+ return c1.version == c2.version
+ && c1.defaultChecks == c2.defaultChecks
+ && c1.supportedChecks == c2.supportedChecks;
+}
+
+bool operator!=(const ClazyStandaloneInfo &c1, const ClazyStandaloneInfo &c2)
+{
+ return !(c1 == c2);
+}
+
+bool operator==(const ClazyCheck &c1, const ClazyCheck &c2)
+{
+ return c1.name == c2.name
+ && c1.level == c2.level
+ && c1.topics == c2.topics;
+}
+
+bool operator!=(const ClazyCheck &c1, const ClazyCheck &c2)
+{
+ return !(c1 == c2);
+}
+
} // namespace Internal
} // namespace ClangTools
diff --git a/src/plugins/clangtools/executableinfo.h b/src/plugins/clangtools/executableinfo.h
index 5db586b5356..f828afb70ac 100644
--- a/src/plugins/clangtools/executableinfo.h
+++ b/src/plugins/clangtools/executableinfo.h
@@ -32,6 +32,9 @@ public:
QString name;
int level;
QStringList topics;
+
+ friend bool operator==(const ClazyCheck &c1, const ClazyCheck &c2);
+ friend bool operator!=(const ClazyCheck &c1, const ClazyCheck &c2);
};
using ClazyChecks = QVector<ClazyCheck>;
@@ -43,6 +46,9 @@ public:
QVersionNumber version;
QStringList defaultChecks;
ClazyChecks supportedChecks;
+
+ friend bool operator==(const ClazyStandaloneInfo &c1, const ClazyStandaloneInfo &c2);
+ friend bool operator!=(const ClazyStandaloneInfo &c1, const ClazyStandaloneInfo &c2);
};
} // namespace Internal
diff --git a/src/plugins/cmakeprojectmanager/cmakesettingspage.cpp b/src/plugins/cmakeprojectmanager/cmakesettingspage.cpp
index 11e109e3c80..c15247efc12 100644
--- a/src/plugins/cmakeprojectmanager/cmakesettingspage.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakesettingspage.cpp
@@ -697,9 +697,7 @@ void CMakeToolConfigWidget::redetect()
// Step 1: Detect
const IDeviceConstPtr dev = currentDevice();
QTC_ASSERT(dev, return);
- const FilePath root = dev->rootPath();
- auto toAdd
- = CMakeToolManager::autoDetectCMakeTools(dev->systemEnvironment().mappedPath(root), root);
+ auto toAdd = CMakeToolManager::autoDetectCMakeTools(dev->toolSearchPaths(), dev->rootPath());
// Step 2: Match existing against newly detected.
QList<Id> toRemove;
diff --git a/src/plugins/coreplugin/locator/locator.cpp b/src/plugins/coreplugin/locator/locator.cpp
index e8ef35f2419..0e530b47960 100644
--- a/src/plugins/coreplugin/locator/locator.cpp
+++ b/src/plugins/coreplugin/locator/locator.cpp
@@ -47,8 +47,46 @@ static Locator *m_instance = nullptr;
const char kDirectoryFilterPrefix[] = "directory";
const char kUrlFilterPrefix[] = "url";
-const char kUseCenteredPopup[] = "UseCenteredPopupForShortcut";
-const char kUseTabCompletion[] = "UseTabCompletion";
+
+LocatorSettings::LocatorSettings()
+{
+ setAutoApply(false);
+ setSettingsGroup("Locator");
+
+ useCenteredPopup.setSettingsKey("UseCenteredPopupForShortcut");
+ useCenteredPopup.setDefaultValue(false);
+ useCenteredPopup.setLabelText(Tr::tr("Open as Centered Popup"));
+
+ useTabCompletion.setSettingsKey("UseTabCompletion");
+ useTabCompletion.setDefaultValue(true);
+ useTabCompletion.setLabelText(Tr::tr("Use Tab Completion"));
+
+ relativePaths.setSettingsKey("RelativePaths");
+ relativePaths.setDefaultValue(false);
+ relativePaths.setLabelText(Tr::tr("Show Paths in Relation to Active Project"));
+ relativePaths.setToolTip(
+ Tr::tr("Locator filters show relative paths to the active project when possible."));
+
+ refreshInterval.setSettingsKey("RefreshInterval");
+ refreshInterval.setRange(0, 320);
+ refreshInterval.setSingleStep(5);
+ refreshInterval.setDefaultValue(60);
+ //: short for "minutes"
+ refreshInterval.setSuffix(Tr::tr(" min"));
+ refreshInterval.setLabelText(Tr::tr("Refresh interval:"));
+ refreshInterval.setToolTip(
+ Tr::tr(
+ "Locator filters that do not update their cached data immediately, such as the "
+ "custom directory filters, update it after this time interval."));
+
+ readSettings();
+}
+
+LocatorSettings &locatorSettings()
+{
+ static LocatorSettings theSettings;
+ return theSettings;
+}
class LocatorData
{
@@ -160,30 +198,7 @@ void Locator::aboutToShutdown()
void Locator::loadSettings()
{
namespace DB = SettingsDatabase;
- // check if we have to read old settings
- // TOOD remove a few versions after 4.15
- const QString settingsGroup = DB::contains("Locator") ? QString("Locator")
- : QString("QuickOpen");
- const Settings def;
- DB::beginGroup(settingsGroup);
- // TODO SettingsDatabase just for old settings from QtC < 16.0
- // when removed, the defaults need to move to the ICore::settings() code path below
- {
- m_refreshTimer.setInterval(
- minutes(DB::value("RefreshInterval", int(def.refreshInterval / 1min)).toInt()));
- m_settings.relativePaths = DB::value("RelativePaths", def.relativePaths).toBool();
- m_settings.useCenteredPopup = DB::value(kUseCenteredPopup, def.useCenteredPopup).toBool();
- }
- ICore::settings()->withGroup("Locator", [this](QtcSettings *settings) {
- m_refreshTimer.setInterval(
- minutes(settings->value("RefreshInterval", refreshInterval()).toInt()));
- m_settings.relativePaths
- = settings->value("RelativePaths", m_settings.relativePaths).toBool();
- m_settings.useCenteredPopup
- = settings->value(kUseCenteredPopup, m_settings.useCenteredPopup).toBool();
- m_settings.useTabCompletion
- = settings->value(kUseTabCompletion, m_settings.useTabCompletion).toBool();
- });
+ DB::beginGroup("Locator");
for (ILocatorFilter *filter : std::as_const(m_filters)) {
if (DB::contains(filter->id().toString())) {
@@ -215,8 +230,19 @@ void Locator::loadSettings()
DB::endGroup();
DB::endGroup();
- if (m_refreshTimer.interval() > 0)
+ const auto updateTimer = [this] {
+ const int interval = locatorSettings().refreshInterval();
+ if (interval < 1) {
+ m_refreshTimer.stop();
+ m_refreshTimer.setInterval(0);
+ return;
+ }
+ m_refreshTimer.setInterval(minutes(interval));
m_refreshTimer.start();
+ };
+ locatorSettings().refreshInterval.addOnChanged(this, updateTimer);
+ updateTimer();
+
m_settingsInitialized = true;
setFilters(m_filters + customFilters);
}
@@ -305,17 +331,10 @@ void Locator::saveSettings() const
if (!m_settingsInitialized)
return;
- const Settings def;
namespace DB = SettingsDatabase;
DB::beginTransaction();
DB::beginGroup("Locator");
DB::remove(QString());
- // TODO SettingsDatabase only for backward compatibility < 16.0
- {
- DB::setValue("RefreshInterval", refreshInterval());
- DB::setValue("RelativePaths", relativePaths());
- DB::setValueWithDefault(kUseCenteredPopup, m_settings.useCenteredPopup, def.useCenteredPopup);
- }
for (ILocatorFilter *filter : m_filters) {
if (!m_customFilters.contains(filter) && filter->id().isValid()) {
const QByteArray state = filter->saveState();
@@ -337,15 +356,7 @@ void Locator::saveSettings() const
DB::endGroup();
DB::endTransaction();
- ICore::settings()->withGroup("Locator", [this, &def](QtcSettings *settings) {
- settings->setValueWithDefault(
- "RefreshInterval", refreshInterval(), int(def.refreshInterval / 1min));
- settings->setValueWithDefault("RelativePaths", m_settings.relativePaths, def.relativePaths);
- settings->setValueWithDefault(
- kUseCenteredPopup, m_settings.useCenteredPopup, def.useCenteredPopup);
- settings->setValueWithDefault(
- kUseTabCompletion, m_settings.useTabCompletion, def.useTabCompletion);
- });
+ locatorSettings().writeSettings();
}
/*!
@@ -378,52 +389,6 @@ void Locator::setCustomFilters(QList<ILocatorFilter *> filters)
m_customFilters = filters;
}
-int Locator::refreshInterval() const
-{
- return m_refreshTimer.interval() / 60000;
-}
-
-void Locator::setRefreshInterval(int interval)
-{
- if (interval < 1) {
- m_refreshTimer.stop();
- m_refreshTimer.setInterval(0);
- return;
- }
- m_refreshTimer.setInterval(minutes(interval));
- m_refreshTimer.start();
-}
-
-bool Locator::relativePaths() const
-{
- return m_settings.relativePaths;
-}
-
-void Locator::setRelativePaths(bool use)
-{
- m_settings.relativePaths = use;
-}
-
-bool Locator::useCenteredPopupForShortcut()
-{
- return m_instance->m_settings.useCenteredPopup;
-}
-
-void Locator::setUseCenteredPopupForShortcut(bool center)
-{
- m_instance->m_settings.useCenteredPopup = center;
-}
-
-bool Locator::useTabCompletion()
-{
- return m_instance->m_settings.useTabCompletion;
-}
-
-void Locator::setUseTabCompletion(bool useTabCompletion)
-{
- m_instance->m_settings.useTabCompletion = useTabCompletion;
-}
-
void Locator::refresh(const QList<ILocatorFilter *> &filters)
{
if (ExtensionSystem::PluginManager::isShuttingDown())
diff --git a/src/plugins/coreplugin/locator/locator.h b/src/plugins/coreplugin/locator/locator.h
index 670be56a48a..1bc36eab95c 100644
--- a/src/plugins/coreplugin/locator/locator.h
+++ b/src/plugins/coreplugin/locator/locator.h
@@ -7,6 +7,7 @@
#include "../actionmanager/command.h"
#include <extensionsystem/iplugin.h>
+#include <utils/aspects.h>
#include <QtTaskTree/QSingleTaskTreeRunner>
@@ -19,6 +20,18 @@ namespace Internal {
class LocatorData;
class LocatorWidget;
+struct LocatorSettings : public Utils::AspectContainer
+{
+ LocatorSettings();
+
+ Utils::BoolAspect useCenteredPopup{this};
+ Utils::BoolAspect useTabCompletion{this};
+ Utils::BoolAspect relativePaths{this};
+ Utils::IntegerAspect refreshInterval{this}; // minutes
+};
+
+LocatorSettings &locatorSettings();
+
class Locator : public QObject
{
Q_OBJECT
@@ -38,15 +51,6 @@ public:
QList<ILocatorFilter *> customFilters();
void setFilters(QList<ILocatorFilter *> f);
void setCustomFilters(QList<ILocatorFilter *> f);
- int refreshInterval() const;
- void setRefreshInterval(int interval);
- bool relativePaths() const;
- void setRelativePaths(bool use);
-
- static bool useCenteredPopupForShortcut();
- static void setUseCenteredPopupForShortcut(bool center);
- static bool useTabCompletion();
- static void setUseTabCompletion(bool useTabCompletion);
static void showFilter(ILocatorFilter *filter, LocatorWidget *widget);
@@ -64,17 +68,8 @@ private:
LocatorData *m_locatorData = nullptr;
- struct Settings
- {
- bool useCenteredPopup = false;
- bool useTabCompletion = true;
- bool relativePaths = false;
- // only for the default:
- const std::chrono::minutes refreshInterval = std::chrono::minutes(60);
- };
-
bool m_settingsInitialized = false;
- Settings m_settings;
+ LocatorSettings m_settings;
QList<ILocatorFilter *> m_filters;
QList<ILocatorFilter *> m_customFilters;
QMap<Utils::Id, QAction *> m_filterActionMap;
diff --git a/src/plugins/coreplugin/locator/locatormanager.cpp b/src/plugins/coreplugin/locator/locatormanager.cpp
index 9b844065c65..26fd32f5775 100644
--- a/src/plugins/coreplugin/locator/locatormanager.cpp
+++ b/src/plugins/coreplugin/locator/locatormanager.cpp
@@ -35,7 +35,7 @@ static LocatorWidget *locatorWidget()
// if that is a popup, try to find a better one
if (window->windowFlags() & Qt::Popup && window->parentWidget())
window = window->parentWidget()->window();
- if (!Locator::useCenteredPopupForShortcut()) {
+ if (!locatorSettings().useCenteredPopup()) {
if (auto *widget = Aggregation::query<LocatorWidget>(window)) {
if (popup)
popup->close();
diff --git a/src/plugins/coreplugin/locator/locatorsettingspage.cpp b/src/plugins/coreplugin/locator/locatorsettingspage.cpp
index 8419b78f342..74ebd92c73a 100644
--- a/src/plugins/coreplugin/locator/locatorsettingspage.cpp
+++ b/src/plugins/coreplugin/locator/locatorsettingspage.cpp
@@ -259,24 +259,6 @@ public:
auto addButton = new QPushButton(Tr::tr("Add..."));
- auto refreshIntervalLabel = new QLabel(Tr::tr("Refresh interval:"));
- refreshIntervalLabel->setToolTip(
- Tr::tr("Locator filters that do not update their cached data immediately, such as the "
- "custom directory filters, update it after this time interval."));
-
- m_refreshInterval = new QSpinBox;
- m_refreshInterval->setToolTip(refreshIntervalLabel->toolTip());
- m_refreshInterval->setSuffix(Tr::tr(" min"));
- m_refreshInterval->setFrame(true);
- m_refreshInterval->setButtonSymbols(QAbstractSpinBox::PlusMinus);
- m_refreshInterval->setMaximum(320);
- m_refreshInterval->setSingleStep(5);
- m_refreshInterval->setValue(60);
-
- m_relativePaths = new QCheckBox(Tr::tr("Show Paths in Relation to Active Project"));
- m_relativePaths->setToolTip(
- Tr::tr("Locator filters show relative paths to the active project when possible."));
-
auto filterEdit = new FancyLineEdit;
filterEdit->setFiltering(true);
@@ -316,6 +298,8 @@ public:
m_editButton = new QPushButton(Tr::tr("Edit..."));
m_editButton->setEnabled(false);
+ const LocatorSettings &settings = locatorSettings();
+
using namespace Layouting;
Column buttons{addButton, m_removeButton, m_editButton, st};
@@ -324,8 +308,10 @@ public:
Grid {
filterEdit, br,
m_filterList, buttons, br,
- Span(2, Row{refreshIntervalLabel, m_refreshInterval, st}), br,
- Span(2, Row{m_relativePaths, st})
+ Column {
+ Row {settings.refreshInterval, st},
+ settings.relativePaths
+ }
}.attachTo(this);
// clang-format on
@@ -360,8 +346,6 @@ public:
});
addButton->setMenu(addMenu);
- m_refreshInterval->setValue(m_plugin->refreshInterval());
- m_relativePaths->setChecked(m_plugin->relativePaths());
saveFilterStates();
}
@@ -382,8 +366,6 @@ private:
Utils::TreeView *m_filterList;
QPushButton *m_removeButton;
QPushButton *m_editButton;
- QSpinBox *m_refreshInterval;
- QCheckBox *m_relativePaths;
Locator *m_plugin = nullptr;
Utils::TreeModel<> *m_model = nullptr;
QSortFilterProxyModel *m_proxyModel = nullptr;
@@ -406,8 +388,7 @@ void LocatorSettingsWidget::apply()
// Pass the new configuration on to the plugin
m_plugin->setFilters(m_filters);
m_plugin->setCustomFilters(m_customFilters);
- m_plugin->setRefreshInterval(m_refreshInterval->value());
- m_plugin->setRelativePaths(m_relativePaths->isChecked());
+ locatorSettings().apply();
requestRefresh();
m_plugin->saveSettings();
saveFilterStates();
diff --git a/src/plugins/coreplugin/locator/locatorwidget.cpp b/src/plugins/coreplugin/locator/locatorwidget.cpp
index 4eca0ab741f..cb238bb60c2 100644
--- a/src/plugins/coreplugin/locator/locatorwidget.cpp
+++ b/src/plugins/coreplugin/locator/locatorwidget.cpp
@@ -168,7 +168,7 @@ QVariant LocatorModel::data(const QModelIndex &index, int role) const
if (index.column() == DisplayNameColumn)
return m_entries.at(index.row()).displayName;
if (index.column() == ExtraInfoColumn) {
- if (Locator::instance()->relativePaths()) {
+ if (locatorSettings().relativePaths()) {
return ICore::pathRelativeToActiveProject(FilePath::fromUserInput(m_entries.at(index.row()).extraInfo)).toUserOutput();
} else {
return m_entries.at(index.row()).extraInfo;
@@ -512,7 +512,7 @@ void CompletionList::keyPressEvent(QKeyEvent *event)
{
switch (event->key()) {
case Qt::Key_Tab:
- if (Locator::useTabCompletion()) {
+ if (locatorSettings().useTabCompletion()) {
emit completionRequested(currentIndex());
return;
}
@@ -576,8 +576,8 @@ bool CompletionList::eventFilter(QObject *watched, QEvent *event)
LocatorWidget::LocatorWidget(Locator *locator)
: m_locatorModel(new LocatorModel(this))
, m_filterMenu(new QMenu(this))
- , m_centeredPopupAction(new QAction(Tr::tr("Open as Centered Popup"), this))
- , m_useTabCompletion(new QAction(Tr::tr("Use Tab Completion"), this))
+ , m_centeredPopupAction(new QAction(locatorSettings().useCenteredPopup.labelText(), this))
+ , m_useTabCompletion(new QAction(locatorSettings().useTabCompletion.labelText(), this))
, m_refreshAction(new QAction(Tr::tr("Refresh"), this))
, m_configureAction(new QAction(ICore::msgShowOptionsDialog(), this))
, m_fileLineEdit(new FancyLineEdit)
@@ -610,24 +610,26 @@ LocatorWidget::LocatorWidget(Locator *locator)
this->installEventFilter(this);
m_centeredPopupAction->setCheckable(true);
- m_centeredPopupAction->setChecked(Locator::useCenteredPopupForShortcut());
+ m_centeredPopupAction->setChecked(locatorSettings().useCenteredPopup());
m_useTabCompletion->setCheckable(true);
- m_useTabCompletion->setChecked(Locator::useTabCompletion());
+ m_useTabCompletion->setChecked(locatorSettings().useTabCompletion());
connect(m_filterMenu, &QMenu::aboutToShow, this, [this] {
- m_centeredPopupAction->setChecked(Locator::useCenteredPopupForShortcut());
- m_useTabCompletion->setChecked(Locator::useTabCompletion());
+ m_centeredPopupAction->setChecked(locatorSettings().useCenteredPopup());
+ m_useTabCompletion->setChecked(locatorSettings().useTabCompletion());
});
Utils::addToolTipsToMenu(m_filterMenu);
connect(m_centeredPopupAction, &QAction::toggled, locator, [locator](bool toggled) {
- if (toggled != Locator::useCenteredPopupForShortcut()) {
- Locator::setUseCenteredPopupForShortcut(toggled);
+ if (toggled != locatorSettings().useCenteredPopup()) {
+ locatorSettings().useCenteredPopup.setValue(toggled);
QMetaObject::invokeMethod(locator, [] { LocatorManager::show({}); });
}
});
- connect(m_useTabCompletion, &QAction::toggled, locator, &Locator::setUseTabCompletion);
+ connect(m_useTabCompletion, &QAction::toggled, locator, [](bool checked) {
+ locatorSettings().useTabCompletion.setValue(checked);
+ });
m_filterMenu->addAction(m_centeredPopupAction);
m_filterMenu->addAction(m_useTabCompletion);
diff --git a/src/plugins/debugger/debuggeritemmanager.cpp b/src/plugins/debugger/debuggeritemmanager.cpp
index 2a7de0a0095..67009dd517f 100644
--- a/src/plugins/debugger/debuggeritemmanager.cpp
+++ b/src/plugins/debugger/debuggeritemmanager.cpp
@@ -203,7 +203,7 @@ public:
void cancel();
DebuggerTreeItem *currentTreeItem();
- void detectDebuggers(const IDeviceConstPtr &device);
+ void detectDebuggers(const IDeviceConstPtr &device, const FilePaths &searchPaths);
void restoreDebuggers();
void saveDebuggers();
@@ -922,15 +922,15 @@ void DebuggerItemModel::restoreDebuggers()
readDebuggers(userSettingsFileName(), false);
// Auto detect current.
- detectDebuggers(DeviceManager::defaultDesktopDevice());
+ const IDeviceConstPtr desktopDevice = DeviceManager::defaultDesktopDevice();
+ if (QTC_GUARD(desktopDevice))
+ detectDebuggers(desktopDevice, desktopDevice->systemEnvironment().path());
}
-void DebuggerItemModel::detectDebuggers(const IDeviceConstPtr &device)
+void DebuggerItemModel::detectDebuggers(const IDeviceConstPtr &device, const FilePaths &searchPaths)
{
QTC_ASSERT(device, return);
- const FilePaths searchPaths = Utils::transform(
- device->systemEnvironment().path(),
- [root = device->rootPath()](const FilePath &raw) { return root.withNewMappedPath(raw); });
+
autoDetectGdbOrLldbDebuggers(searchPaths, {});
if (device->id() == ProjectExplorer::Constants::DESKTOP_DEVICE_ID) {
autoDetectCdbDebuggers();
@@ -1222,7 +1222,11 @@ public:
connect(m_delButton, &QAbstractButton::clicked,
this, &DebuggerSettingsPageWidget::removeDebugger, Qt::QueuedConnection);
connect(m_detectButton , &QAbstractButton::clicked,
- this, [this] { itemModel().detectDebuggers(currentDevice()); });
+ this, [this] {
+ const IDeviceConstPtr dev = currentDevice();
+ QTC_ASSERT(dev, return);
+ itemModel().detectDebuggers(dev, dev->toolSearchPaths());
+ });
m_deviceComboBox->setCurrentIndex(
m_deviceModel->indexOf(DeviceManager::defaultDesktopDevice()));
@@ -1235,6 +1239,11 @@ public:
m_itemConfigWidget = new DebuggerItemConfigWidget;
m_container->setWidget(m_itemConfigWidget);
updateButtons();
+
+ connect(DeviceManager::instance(), &DeviceManager::toolDetectionRequested, this,
+ [](Id devId, const FilePaths &searchPaths) {
+ itemModel().detectDebuggers(DeviceManager::find(devId), searchPaths);
+ });
}
void apply() final
diff --git a/src/plugins/projectexplorer/buildsteplist.cpp b/src/plugins/projectexplorer/buildsteplist.cpp
index d0badc4b5c4..b01cc1f3bf9 100644
--- a/src/plugins/projectexplorer/buildsteplist.cpp
+++ b/src/plugins/projectexplorer/buildsteplist.cpp
@@ -145,6 +145,13 @@ QList<BuildStep *> BuildStepList::steps() const
return m_steps;
}
+QList<BuildStep *> BuildStepList::takeSteps()
+{
+ QList<BuildStep *> steps = m_steps;
+ m_steps.clear();
+ return steps;
+}
+
BuildStep *BuildStepList::firstStepWithId(Utils::Id id) const
{
return Utils::findOrDefault(m_steps, Utils::equal(&BuildStep::id, id));
diff --git a/src/plugins/projectexplorer/buildsteplist.h b/src/plugins/projectexplorer/buildsteplist.h
index 6b49ee3095e..fe9f2905d68 100644
--- a/src/plugins/projectexplorer/buildsteplist.h
+++ b/src/plugins/projectexplorer/buildsteplist.h
@@ -28,6 +28,7 @@ public:
void clear();
QList<BuildStep *> steps() const;
+ QList<BuildStep *> takeSteps();
template <class BS> BS *firstOfType() const {
BS *bs = nullptr;
diff --git a/src/plugins/projectexplorer/devicesupport/idevice.cpp b/src/plugins/projectexplorer/devicesupport/idevice.cpp
index 4197a3b709c..8556a3d829c 100644
--- a/src/plugins/projectexplorer/devicesupport/idevice.cpp
+++ b/src/plugins/projectexplorer/devicesupport/idevice.cpp
@@ -296,6 +296,11 @@ bool IDevice::supportsFileTransferMethod(FileTransferMethod method) const
return false;
}
+FilePaths IDevice::toolSearchPaths() const
+{
+ return d->autoDetectionPaths();
+}
+
IDevice::RecipeAndSearchPath IDevice::autoDetectDeviceToolsRecipe()
{
struct Data
diff --git a/src/plugins/projectexplorer/devicesupport/idevice.h b/src/plugins/projectexplorer/devicesupport/idevice.h
index 2dacfa7e1a0..019c794d140 100644
--- a/src/plugins/projectexplorer/devicesupport/idevice.h
+++ b/src/plugins/projectexplorer/devicesupport/idevice.h
@@ -295,6 +295,7 @@ public:
virtual bool supportsQtTargetDeviceType(const QSet<Utils::Id> &targetDeviceTypes) const;
+ Utils::FilePaths toolSearchPaths() const;
class RecipeAndSearchPath {
public:
QtTaskTree::Group recipe;
diff --git a/src/plugins/projectexplorer/gcctoolchain.cpp b/src/plugins/projectexplorer/gcctoolchain.cpp
index 5d023c93062..266dffff271 100644
--- a/src/plugins/projectexplorer/gcctoolchain.cpp
+++ b/src/plugins/projectexplorer/gcctoolchain.cpp
@@ -1473,31 +1473,27 @@ Toolchains GccToolchainFactory::autoDetect(const ToolchainDetector &detector) co
if (!m_autoDetecting)
return {};
- const bool isLocal = detector.device->type() == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE;
+ const FilePath rootPath = detector.device->rootPath();
+ const OsType os = detector.device->osType();
FilePaths searchPaths = detector.searchPaths;
- if (!isLocal) {
- if (searchPaths.isEmpty())
- searchPaths = detector.device->systemEnvironment().path();
- searchPaths = Utils::transform(searchPaths, [&](const FilePath &onDevice) {
- return detector.device->filePath(onDevice.path());
- });
- } else if (searchPaths.isEmpty()) {
- searchPaths = Environment::systemEnvironment().path();
+ if (searchPaths.isEmpty())
+ searchPaths = detector.device->systemEnvironment().mappedPath(rootPath);
+
+ if (os == OsTypeWindows) {
searchPaths << gnuSearchPathsFromRegistry();
searchPaths << atmelSearchPathsFromRegistry();
searchPaths << renesasRl78SearchPathsFromRegistry();
- if (HostOsInfo::isMacHost()) {
- searchPaths << "/opt/homebrew/opt/ccache/libexec" // homebrew arm
- << "/usr/local/opt/ccache/libexec" // homebrew intel
- << "/opt/local/libexec/ccache"; // macports, no links are created automatically though
- }
- if (HostOsInfo::isAnyUnixHost()) {
- FilePath ccachePath = "/usr/lib/ccache/bin";
- if (!ccachePath.exists())
- ccachePath = "/usr/lib/ccache";
- if (ccachePath.exists() && !searchPaths.contains(ccachePath))
- searchPaths << ccachePath;
- }
+ } else if (os == OsTypeMac) {
+ searchPaths << rootPath.withNewPath("/opt/homebrew/opt/ccache/libexec") // homebrew arm
+ << rootPath.withNewPath("/usr/local/opt/ccache/libexec") // homebrew intel
+ << rootPath.withNewPath("/opt/local/libexec/ccache"); // macports, no links are created automatically though
+ }
+ if (os == OsTypeMac || os == OsTypeLinux || os == OsTypeOtherUnix) {
+ FilePath ccachePath = rootPath.withNewPath("/usr/lib/ccache/bin");
+ if (!ccachePath.exists())
+ ccachePath = rootPath.withNewPath("/usr/lib/ccache");
+ if (ccachePath.exists() && !searchPaths.contains(ccachePath))
+ searchPaths << ccachePath;
}
FilePaths executables;
@@ -1510,17 +1506,15 @@ Toolchains GccToolchainFactory::autoDetect(const ToolchainDetector &detector) co
}, {nameFilters, QDir::Files | QDir::Executable });
// Gcc is almost never what you want on macOS, but it is by default found in /usr/bin
- if (HostOsInfo::isMacHost() && detector.device->type() == Constants::DESKTOP_DEVICE_TYPE) {
- executables.removeOne(FilePath::fromPathPart(u"/usr/bin/gcc"));
- executables.removeOne(FilePath::fromPathPart(u"/usr/bin/g++"));
- executables.removeOne(FilePath::fromPathPart(u"/usr/bin/llvm-gcc"));
- executables.removeOne(FilePath::fromPathPart(u"/usr/bin/llvm-g++"));
+ if (detector.device->osType() == OsTypeMac) {
+ executables.removeOne(rootPath.withNewPath("/usr/bin/gcc"));
+ executables.removeOne(rootPath.withNewPath("/usr/bin/g++"));
+ executables.removeOne(rootPath.withNewPath("/usr/bin/llvm-gcc"));
+ executables.removeOne(rootPath.withNewPath("/usr/bin/llvm-g++"));
}
Utils::sort(executables);
- const OsType os = detector.device->osType();
-
Toolchains result;
// Linux ICC
@@ -1555,7 +1549,7 @@ Toolchains GccToolchainFactory::autoDetect(const ToolchainDetector &detector) co
GccToolchain::Clang));
known.append(tcs);
- if (isLocal)
+ if (detector.device->type() == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE)
tcs.append(autoDetectSdkClangToolchain(known));
result += tcs;
diff --git a/src/plugins/projectexplorer/msvctoolchain.cpp b/src/plugins/projectexplorer/msvctoolchain.cpp
index 398faf010d6..fd56cfe3c6d 100644
--- a/src/plugins/projectexplorer/msvctoolchain.cpp
+++ b/src/plugins/projectexplorer/msvctoolchain.cpp
@@ -1612,6 +1612,9 @@ public:
static ClangClInfo getInfo(const FilePath &filePath);
+ friend bool operator==(const ClangClInfo &lhs, const ClangClInfo &rhs);
+ friend bool operator!=(const ClangClInfo &lhs, const ClangClInfo &rhs);
+
private:
FilePath m_filePath;
QVersionNumber m_version;
@@ -2375,6 +2378,17 @@ ClangClInfo ClangClInfo::getInfo(const FilePath &filePath)
return info ? *info : ClangClInfo();
}
+bool operator==(const ClangClInfo &lhs, const ClangClInfo &rhs)
+{
+ return lhs.m_filePath == rhs.m_filePath && lhs.m_version == rhs.m_version
+ && lhs.m_defaultAbi == rhs.m_defaultAbi;
+}
+
+bool operator!=(const ClangClInfo &lhs, const ClangClInfo &rhs)
+{
+ return !(lhs == rhs);
+}
+
} // namespace ProjectExplorer::Internal
Q_DECLARE_METATYPE(ProjectExplorer::Internal::MsvcToolchain::Platform)
diff --git a/src/plugins/projectexplorer/toolchain.h b/src/plugins/projectexplorer/toolchain.h
index a3803d086f7..43ee1286897 100644
--- a/src/plugins/projectexplorer/toolchain.h
+++ b/src/plugins/projectexplorer/toolchain.h
@@ -352,7 +352,7 @@ public:
const Toolchains alreadyKnown;
const IDeviceConstPtr device;
- const Utils::FilePaths searchPaths; // If empty use device path and/or magic.
+ const Utils::FilePaths searchPaths; // If empty use PATH.
};
class PROJECTEXPLORER_EXPORT ToolchainFactory
diff --git a/src/plugins/projectexplorer/toolchainmanager.cpp b/src/plugins/projectexplorer/toolchainmanager.cpp
index a655f5c1bc3..f91599d4135 100644
--- a/src/plugins/projectexplorer/toolchainmanager.cpp
+++ b/src/plugins/projectexplorer/toolchainmanager.cpp
@@ -120,11 +120,7 @@ void ToolchainManager::restoreToolchains()
if (!device)
return;
- // FIXME: ToolchainDetector needs extension to instruct downstream code to
- // look at all possible combinations of PATH and explicit search paths,
- // so that the settings from the device widget can be honored.
- ToolchainDetector detector(m_instance->toolchains(), device, {});
-
+ ToolchainDetector detector(m_instance->toolchains(), device, device->toolSearchPaths());
Toolchains toRegister;
for (ToolchainFactory *f : ToolchainFactory::allToolchainFactories()) {
for (Toolchain * const tc : f->autoDetect(detector)) {
diff --git a/src/plugins/projectexplorer/toolchainoptionspage.cpp b/src/plugins/projectexplorer/toolchainoptionspage.cpp
index d56fbd0b06c..4b086d65132 100644
--- a/src/plugins/projectexplorer/toolchainoptionspage.cpp
+++ b/src/plugins/projectexplorer/toolchainoptionspage.cpp
@@ -334,10 +334,13 @@ public:
markForRemoval(item);
});
- m_filterModel.setDevice(DeviceManager::defaultDesktopDevice());
- connect(m_deviceComboBox, &QComboBox::currentIndexChanged, this, [this](int idx) {
- m_filterModel.setDevice(DeviceManager::deviceAt(idx));
- });
+ const auto updateDevice = [this](int index) {
+ m_filterModel.setDevice(m_deviceManagerModel.device(index));
+ };
+ connect(m_deviceComboBox, &QComboBox::currentIndexChanged, this, updateDevice);
+ m_deviceComboBox->setCurrentIndex(
+ m_deviceManagerModel.indexForId(ProjectExplorer::Constants::DESKTOP_DEVICE_ID));
+ updateDevice(m_deviceComboBox->currentIndex());
updateState();
}
@@ -531,8 +534,10 @@ void ToolChainOptionsWidget::redetectToolchains()
ToolchainManager::resetBadToolchains();
// Step 2: Re-detect toolchains.
+ const IDeviceConstPtr device = currentDevice();
+ QTC_ASSERT(device, return);
for (ToolchainFactory *f : ToolchainFactory::allToolchainFactories()) {
- const ToolchainDetector detector(knownTcs, currentDevice(), {}); // FIXME: Pass search paths
+ const ToolchainDetector detector(knownTcs, device, device->toolSearchPaths());
for (Toolchain * const tc : f->autoDetect(detector)) {
if (knownTcs.contains(tc))
continue;
diff --git a/src/plugins/python/pythonsettings.cpp b/src/plugins/python/pythonsettings.cpp
index e00d16e7179..6c257aa2c90 100644
--- a/src/plugins/python/pythonsettings.cpp
+++ b/src/plugins/python/pythonsettings.cpp
@@ -151,22 +151,19 @@ class InterpreterDetailsWidget : public QWidget
{
Q_OBJECT
public:
- InterpreterDetailsWidget(QWidget *parent)
- : QWidget(parent)
- , m_name(new QLineEdit)
- , m_executable(new PathChooser())
+ InterpreterDetailsWidget()
{
- m_executable->setExpectedKind(PathChooser::ExistingCommand);
- m_executable->setAllowPathFromDevice(true);
+ m_executable.setExpectedKind(PathChooser::ExistingCommand);
+ m_executable.setAllowPathFromDevice(true);
- connect(m_name, &QLineEdit::textChanged, this, &InterpreterDetailsWidget::changed);
- connect(m_executable, &PathChooser::textChanged, this, &InterpreterDetailsWidget::changed);
+ connect(&m_name, &QLineEdit::textChanged, this, &InterpreterDetailsWidget::changed);
+ connect(&m_executable, &PathChooser::textChanged, this, &InterpreterDetailsWidget::changed);
using namespace Layouting;
Form {
- Tr::tr("Name:"), m_name, br,
- Tr::tr("Executable"), m_executable,
+ Tr::tr("Name:"), &m_name, br,
+ Tr::tr("Executable"), &m_executable,
noMargin
}.attachTo(this);
}
@@ -175,18 +172,18 @@ public:
{
QSignalBlocker blocker(this); // do not emit changed when we change the controls here
m_currentInterpreter = interpreter;
- m_name->setText(interpreter.name);
- m_executable->setFilePath(interpreter.command);
+ m_name.setText(interpreter.name);
+ m_executable.setFilePath(interpreter.command);
}
Interpreter toInterpreter()
{
- m_currentInterpreter.command = m_executable->filePath();
- m_currentInterpreter.name = m_name->text();
+ m_currentInterpreter.command = m_executable.filePath();
+ m_currentInterpreter.name = m_name.text();
return m_currentInterpreter;
}
- QLineEdit *m_name = nullptr;
- PathChooser *m_executable = nullptr;
+ QLineEdit m_name;
+ PathChooser m_executable;
Interpreter m_currentInterpreter;
signals:
@@ -210,13 +207,6 @@ public:
}
private:
- QTreeView *m_view = nullptr;
- InterpreterDetailsWidget *m_detailsWidget = nullptr;
- QPushButton *m_deleteButton = nullptr;
- QPushButton *m_makeDefaultButton = nullptr;
- QPushButton *m_generateKitButton = nullptr;
- QPushButton *m_cleanButton = nullptr;
-
void currentChanged(const QModelIndex &index, const QModelIndex &previous);
void detailsChanged();
void updateCleanButton();
@@ -226,59 +216,64 @@ private:
void makeDefault();
void generateKit();
void cleanUp();
+
+ QTreeView m_view;
+ InterpreterDetailsWidget m_detailsWidget;
+ QPushButton m_addButton;
+ QPushButton m_deleteButton;
+ QPushButton m_makeDefaultButton;
+ QPushButton m_generateKitButton;
+ QPushButton m_cleanButton;
};
InterpreterOptionsWidget::InterpreterOptionsWidget()
- : m_detailsWidget(new InterpreterDetailsWidget(this))
{
- auto addButton = new QPushButton(Tr::tr("&Add"), this);
+ m_addButton.setText(Tr::tr("&Add"));
- m_deleteButton = new QPushButton(Tr::tr("&Delete"), this);
- m_deleteButton->setEnabled(false);
- m_makeDefaultButton = new QPushButton(Tr::tr("&Make Default"));
- m_makeDefaultButton->setEnabled(false);
- m_generateKitButton = new QPushButton(Tr::tr("&Generate Kit"));
- m_generateKitButton->setEnabled(false);
+ m_deleteButton.setText(Tr::tr("&Delete"));
+ m_deleteButton.setEnabled(false);
+ m_makeDefaultButton.setText(Tr::tr("&Make Default"));
+ m_makeDefaultButton.setEnabled(false);
+ m_generateKitButton.setText(Tr::tr("&Generate Kit"));
+ m_generateKitButton.setEnabled(false);
- m_cleanButton = new QPushButton(Tr::tr("&Clean Up"), this);
- m_cleanButton->setToolTip(Tr::tr("Remove all Python interpreters without a valid executable."));
-
- m_view = new QTreeView(this);
+ m_cleanButton.setText(Tr::tr("&Clean Up"));
+ m_cleanButton.setToolTip(Tr::tr("Remove all Python interpreters without a valid executable."));
using namespace Layouting;
-
- Column buttons {
- addButton,
- m_deleteButton,
- m_makeDefaultButton,
- m_generateKitButton,
- m_cleanButton,
- st
- };
-
- Column {
- Row { m_view, buttons },
- m_detailsWidget
+ Row {
+ Column {
+ m_view,
+ m_detailsWidget
+ },
+ Column {
+ m_addButton,
+ m_deleteButton,
+ m_makeDefaultButton,
+ m_generateKitButton,
+ m_cleanButton,
+ st
+ }
}.attachTo(this);
updateCleanButton();
- m_detailsWidget->hide();
+ m_detailsWidget.hide();
- m_view->setModel(&interpreterModel());
- m_view->setHeaderHidden(true);
- m_view->setSelectionMode(QAbstractItemView::SingleSelection);
- m_view->setSelectionBehavior(QAbstractItemView::SelectItems);
+ m_view.setModel(&interpreterModel());
+ m_view.setHeaderHidden(true);
+ m_view.setSelectionMode(QAbstractItemView::SingleSelection);
+ m_view.setSelectionBehavior(QAbstractItemView::SelectItems);
- connect(addButton, &QPushButton::pressed, this, &InterpreterOptionsWidget::addItem);
- connect(m_deleteButton, &QPushButton::pressed, this, &InterpreterOptionsWidget::deleteItem);
- connect(m_makeDefaultButton, &QPushButton::pressed, this, &InterpreterOptionsWidget::makeDefault);
- connect(m_generateKitButton, &QPushButton::pressed, this, &InterpreterOptionsWidget::generateKit);
- connect(m_cleanButton, &QPushButton::pressed, this, &InterpreterOptionsWidget::cleanUp);
+ connect(&m_addButton, &QPushButton::pressed, this, &InterpreterOptionsWidget::addItem);
+ connect(&m_deleteButton, &QPushButton::pressed, this, &InterpreterOptionsWidget::deleteItem);
+ connect(&m_makeDefaultButton, &QPushButton::pressed, this, &InterpreterOptionsWidget::makeDefault);
+ connect(&m_generateKitButton, &QPushButton::pressed, this, &InterpreterOptionsWidget::generateKit);
+ connect(&m_cleanButton, &QPushButton::pressed, this, &InterpreterOptionsWidget::cleanUp);
- connect(m_detailsWidget, &InterpreterDetailsWidget::changed,
+ connect(&m_detailsWidget, &InterpreterDetailsWidget::changed,
this, &InterpreterOptionsWidget::detailsChanged);
- connect(m_view->selectionModel(), &QItemSelectionModel::currentChanged,
+ connect(m_view.selectionModel(), &QItemSelectionModel::currentChanged,
this, &InterpreterOptionsWidget::currentChanged);
}
@@ -312,27 +307,27 @@ QList<Interpreter> InterpreterModel::interpreterFrom(const QString &detectionSou
void InterpreterOptionsWidget::currentChanged(const QModelIndex &index, const QModelIndex &previous)
{
if (previous.isValid()) {
- interpreterModel().itemAt(previous.row())->itemData = m_detailsWidget->toInterpreter();
+ interpreterModel().itemAt(previous.row())->itemData = m_detailsWidget.toInterpreter();
emit interpreterModel().dataChanged(previous, previous);
}
if (index.isValid()) {
const Interpreter interpreter = interpreterModel().itemAt(index.row())->itemData;
- m_detailsWidget->updateInterpreter(interpreter);
- m_detailsWidget->show();
+ m_detailsWidget.updateInterpreter(interpreter);
+ m_detailsWidget.show();
updateGenerateKitButton(interpreter);
} else {
- m_detailsWidget->hide();
- m_generateKitButton->setEnabled(false);
+ m_detailsWidget.hide();
+ m_generateKitButton.setEnabled(false);
}
- m_deleteButton->setEnabled(index.isValid());
- m_makeDefaultButton->setEnabled(index.isValid());
+ m_deleteButton.setEnabled(index.isValid());
+ m_makeDefaultButton.setEnabled(index.isValid());
}
void InterpreterOptionsWidget::detailsChanged()
{
- const QModelIndex &index = m_view->currentIndex();
+ const QModelIndex &index = m_view.currentIndex();
if (index.isValid()) {
- const Interpreter interpreter = m_detailsWidget->toInterpreter();
+ const Interpreter interpreter = m_detailsWidget.toInterpreter();
interpreterModel().itemAt(index.row())->itemData = interpreter;
emit interpreterModel().dataChanged(index, index);
updateGenerateKitButton(interpreter);
@@ -342,7 +337,7 @@ void InterpreterOptionsWidget::detailsChanged()
void InterpreterOptionsWidget::updateCleanButton()
{
- m_cleanButton->setEnabled(Utils::anyOf(interpreterModel().allData(), [](const Interpreter &interpreter) {
+ m_cleanButton.setEnabled(Utils::anyOf(interpreterModel().allData(), [](const Interpreter &interpreter) {
return !interpreter.command.isExecutableFile();
}));
}
@@ -351,7 +346,7 @@ void InterpreterOptionsWidget::updateGenerateKitButton(const Interpreter &interp
{
bool enabled = !KitManager::kit(Id::fromString(interpreter.id))
&& (!interpreter.command.isLocal() || interpreter.command.isExecutableFile());
- m_generateKitButton->setEnabled(enabled);
+ m_generateKitButton.setEnabled(enabled);
}
void InterpreterOptionsWidget::addItem()
@@ -359,13 +354,13 @@ void InterpreterOptionsWidget::addItem()
const QModelIndex &index = interpreterModel().indexForItem(interpreterModel().appendItem(
{QUuid::createUuid().toString(), QString("Python"), FilePath(), DetectionSource::Manual}));
QTC_ASSERT(index.isValid(), return);
- m_view->setCurrentIndex(index);
+ m_view.setCurrentIndex(index);
updateCleanButton();
}
void InterpreterOptionsWidget::deleteItem()
{
- const QModelIndex &index = m_view->currentIndex();
+ const QModelIndex &index = m_view.currentIndex();
if (index.isValid())
interpreterModel().destroyItem(interpreterModel().itemAt(index.row()));
updateCleanButton();
@@ -533,7 +528,7 @@ static PyLSOptionsPage &pylspOptionsPage()
void InterpreterOptionsWidget::makeDefault()
{
- const QModelIndex &index = m_view->currentIndex();
+ const QModelIndex &index = m_view.currentIndex();
if (index.isValid()) {
QModelIndex defaultIndex = interpreterModel().findIndex([](const Interpreter &interpreter) {
return interpreter.id == s_defaultId;
@@ -547,10 +542,10 @@ void InterpreterOptionsWidget::makeDefault()
void InterpreterOptionsWidget::generateKit()
{
- const QModelIndex &index = m_view->currentIndex();
+ const QModelIndex &index = m_view.currentIndex();
if (index.isValid())
PythonSettings::addKitsForInterpreter(interpreterModel().itemAt(index.row())->itemData, true);
- m_generateKitButton->setEnabled(false);
+ m_generateKitButton.setEnabled(false);
}
void InterpreterOptionsWidget::cleanUp()
diff --git a/src/plugins/qmakeprojectmanager/qmakebuildconfiguration.cpp b/src/plugins/qmakeprojectmanager/qmakebuildconfiguration.cpp
index d33b5a69e41..7b34fce355c 100644
--- a/src/plugins/qmakeprojectmanager/qmakebuildconfiguration.cpp
+++ b/src/plugins/qmakeprojectmanager/qmakebuildconfiguration.cpp
@@ -175,6 +175,8 @@ QmakeBuildConfiguration::QmakeBuildConfiguration(Target *target, Id id)
QmakeBuildConfiguration::~QmakeBuildConfiguration()
{
+ m_makeStepOnlyList.takeSteps();
+
// BuildSystem might send signals during destruction before this QObject
// had a chance to disconnect from it.
disconnect(m_bsParsingFinishedConnection);
@@ -338,6 +340,14 @@ void QmakeBuildConfiguration::setFileNodeBuild(FileNode *node)
m_fileNodeBuild = node;
}
+BuildStepList *QmakeBuildConfiguration::makeStepOnlyList()
+{
+ m_makeStepOnlyList.takeSteps();
+ if (const auto makeStep = buildSteps()->firstStepWithId(Constants::MAKESTEP_BS_ID))
+ m_makeStepOnlyList.appendStep(makeStep);
+ return &m_makeStepOnlyList;
+}
+
FilePath QmakeBuildConfiguration::makefile() const
{
return FilePath::fromString(qmakeBuildSystem()->rootProFile()->singleVariableValue(Variable::Makefile));
diff --git a/src/plugins/qmakeprojectmanager/qmakebuildconfiguration.h b/src/plugins/qmakeprojectmanager/qmakebuildconfiguration.h
index c969d8e0bed..69d3855dcd5 100644
--- a/src/plugins/qmakeprojectmanager/qmakebuildconfiguration.h
+++ b/src/plugins/qmakeprojectmanager/qmakebuildconfiguration.h
@@ -7,6 +7,8 @@
#include <projectexplorer/buildaspects.h>
#include <projectexplorer/buildconfiguration.h>
+#include <projectexplorer/buildsteplist.h>
+#include <projectexplorer/projectexplorerconstants.h>
#include <qtsupport/baseqtversion.h>
#include <qtsupport/qtbuildaspects.h>
@@ -37,6 +39,8 @@ public:
ProjectExplorer::FileNode *fileNodeBuild() const;
void setFileNodeBuild(ProjectExplorer::FileNode *node);
+ ProjectExplorer::BuildStepList *makeStepOnlyList();
+
QtSupport::QtVersion::QmakeBuildConfigs qmakeBuildConfiguration() const;
void setQMakeBuildConfiguration(QtSupport::QtVersion::QmakeBuildConfigs config);
@@ -133,6 +137,8 @@ private:
QtSupport::QtVersion::QmakeBuildConfigs m_qmakeBuildConfiguration;
QmakeProFileNode *m_subNodeBuild = nullptr;
ProjectExplorer::FileNode *m_fileNodeBuild = nullptr;
+ ProjectExplorer::BuildStepList
+ m_makeStepOnlyList{this, ProjectExplorer::Constants::BUILDSTEPS_BUILD};
QMetaObject::Connection m_bsParsingFinishedConnection;
};
diff --git a/src/plugins/qmakeprojectmanager/qmakeproject.cpp b/src/plugins/qmakeprojectmanager/qmakeproject.cpp
index 2445a823c8d..7edd8609a9b 100644
--- a/src/plugins/qmakeprojectmanager/qmakeproject.cpp
+++ b/src/plugins/qmakeprojectmanager/qmakeproject.cpp
@@ -1582,15 +1582,19 @@ void QmakeBuildSystem::buildHelper(Action action, bool isFileBuild, QmakeProFile
bc->setSubNodeBuild(profile->proFileNode());
}
- if (isFileBuild)
+ BuildStepList *buildSteps = bc->buildSteps();
+ if (isFileBuild) {
bc->setFileNodeBuild(buildableFile);
+ if (BuildStepList * const bsl = bc->makeStepOnlyList(); !bsl->isEmpty())
+ buildSteps = bsl;
+ }
if (ProjectExplorerPlugin::saveModifiedFiles()) {
if (action == BUILD)
- BuildManager::buildList(bc->buildSteps());
+ BuildManager::buildList(buildSteps);
else if (action == CLEAN)
BuildManager::buildList(bc->cleanSteps());
else if (action == REBUILD)
- BuildManager::buildLists({bc->cleanSteps(), bc->buildSteps()});
+ BuildManager::buildLists({bc->cleanSteps(), buildSteps});
}
bc->setSubNodeBuild(nullptr);
diff --git a/src/plugins/qtsupport/qtoptionspage.cpp b/src/plugins/qtsupport/qtoptionspage.cpp
index 06403105f04..44477828eb8 100644
--- a/src/plugins/qtsupport/qtoptionspage.cpp
+++ b/src/plugins/qtsupport/qtoptionspage.cpp
@@ -801,8 +801,7 @@ void QtSettingsPageWidget::redetect()
if (!QTC_GUARD(dev))
return;
- const FilePaths qMakes
- = BuildableHelperLibrary::findQtsInEnvironment(dev->systemEnvironment(), dev->rootPath());
+ const FilePaths qMakes = BuildableHelperLibrary::findQtsInPaths(dev->toolSearchPaths());
for (const FilePath &qmakePath : qMakes) {
if (BuildableHelperLibrary::isQtChooser(qmakePath))
continue;
diff --git a/src/plugins/qtsupport/qtsupportconstants.h b/src/plugins/qtsupport/qtsupportconstants.h
index a5e73a3a215..106ae84d964 100644
--- a/src/plugins/qtsupport/qtsupportconstants.h
+++ b/src/plugins/qtsupport/qtsupportconstants.h
@@ -39,6 +39,4 @@ const char KIT_QML_IMPORT_PATH[] = "QtSupport.KitQmlImportPath";
const char KIT_HAS_MERGED_HEADER_PATHS_WITH_QML_IMPORT_PATHS[] =
"QtSupport.KitHasMergedHeaderPathsWithQmlImportPaths";
-const char QMAKE_TOOL_ID[] = "QMakeTool";
-
} // namepsace QtSupport::Constants
diff --git a/src/plugins/qtsupport/qtsupportplugin.cpp b/src/plugins/qtsupport/qtsupportplugin.cpp
index 3317e4d4262..d4c483b3788 100644
--- a/src/plugins/qtsupport/qtsupportplugin.cpp
+++ b/src/plugins/qtsupport/qtsupportplugin.cpp
@@ -11,7 +11,6 @@
#include "qtoutputformatter.h"
#include "qtparser.h"
#include "qtprojectimporter.h"
-#include "qtsupportconstants.h"
#include "qtsupporttr.h"
#include "qttestparser.h"
#include "qtversionmanager.h"
@@ -27,7 +26,6 @@
#include <projectexplorer/buildpropertiessettings.h>
#include <projectexplorer/buildsystem.h>
#include <projectexplorer/devicesupport/idevice.h>
-#include <projectexplorer/jsonwizard/jsonwizardfactory.h>
#include <projectexplorer/project.h>
#include <projectexplorer/projectmanager.h>
#include <projectexplorer/projecttree.h>
@@ -68,23 +66,6 @@ static void processRunnerCallback(ProcessData *data)
data->stdOut = proc.rawStdOut();
}
-class QmakeToolFactory : public DeviceToolAspectFactory
-{
-public:
- QmakeToolFactory()
- {
- setToolId(Constants::QMAKE_TOOL_ID);
- setToolType(DeviceToolAspect::BuildTool);
- setFilePattern({"qmake"});
- setLabelText(Tr::tr("qmake executable:"));
- }
-};
-
-void setupQmakeToolFactory()
-{
- static QmakeToolFactory theQmakeToolFactory;
-}
-
class QtSupportPlugin final : public ExtensionSystem::IPlugin
{
Q_OBJECT
@@ -106,7 +87,6 @@ void QtSupportPlugin::initialize()
#endif
setupQtVersionManager(this);
- setupQmakeToolFactory();
setupDesktopQtVersion();
setupEmbeddedLinuxQtVersion();
diff --git a/src/plugins/qtsupport/qtversionmanager.cpp b/src/plugins/qtsupport/qtversionmanager.cpp
index a01ac526643..8637686c022 100644
--- a/src/plugins/qtsupport/qtversionmanager.cpp
+++ b/src/plugins/qtsupport/qtversionmanager.cpp
@@ -120,7 +120,8 @@ public:
bool restoreQtVersions();
void findSystemQt(const IDeviceConstPtr &device);
- void handleDeviceToolDetectionRequest(Id deviceId);
+ void addQtVersionsFromFilePaths(const FilePaths &filePaths);
+ void handleDeviceToolDetectionRequest(Id deviceId, const FilePaths &searchPaths);
void saveQtVersions();
void updateDocumentation(const QtVersions &added,
@@ -452,6 +453,7 @@ QString QtVersionManagerImpl::qmakePath(const QString &qtchooser, const QString
FilePaths QtVersionManagerImpl::gatherQmakePathsFromQtChooser()
{
+ // FIXME: Desktop-only
const QString qtchooser = QStandardPaths::findExecutable(QStringLiteral("qtchooser"));
if (qtchooser.isEmpty())
return {};
@@ -474,7 +476,12 @@ void QtVersionManagerImpl::findSystemQt(const IDeviceConstPtr &device)
FilePaths systemQMakes = BuildableHelperLibrary::findQtsInEnvironment(
device->systemEnvironment(), device->rootPath());
systemQMakes.append(gatherQmakePathsFromQtChooser());
- for (const FilePath &qmakePath : std::as_const(systemQMakes)) {
+ addQtVersionsFromFilePaths(systemQMakes);
+}
+
+void QtVersionManagerImpl::addQtVersionsFromFilePaths(const FilePaths &filePaths)
+{
+ for (const FilePath &qmakePath : filePaths) {
if (BuildableHelperLibrary::isQtChooser(qmakePath))
continue;
const auto isSameQmake = [qmakePath](const QtVersion *version) {
@@ -489,10 +496,12 @@ void QtVersionManagerImpl::findSystemQt(const IDeviceConstPtr &device)
}
}
-void QtVersionManagerImpl::handleDeviceToolDetectionRequest(Id deviceId)
+void QtVersionManagerImpl::handleDeviceToolDetectionRequest(Id deviceId, const FilePaths &searchPaths)
{
+ Q_UNUSED(deviceId)
+
const VersionMap qtVersions = m_versions;
- findSystemQt(DeviceManager::find(deviceId));
+ addQtVersionsFromFilePaths(BuildableHelperLibrary::findQtsInPaths(searchPaths));
if (qtVersions != m_versions) {
saveQtVersions();
emit QtVersionManager::instance()->qtVersionsChanged(m_versions.keys());
diff --git a/src/plugins/saferenderer/saferenderer.qrc b/src/plugins/saferenderer/saferenderer.qrc
index 84999a48aac..38bad272e12 100644
--- a/src/plugins/saferenderer/saferenderer.qrc
+++ b/src/plugins/saferenderer/saferenderer.qrc
@@ -15,5 +15,12 @@
<file>wizards/qsrapp2_1/qml.qrc.tpl</file>
<file>wizards/qsrapp2_1/safeasset.qrc.tpl</file>
<file>wizards/qsrapp2_1/wizard.json</file>
+ <file>wizards/qsrapp2_2/file.pro</file>
+ <file>wizards/qsrapp2_2/CMakeLists.txt</file>
+ <file>wizards/qsrapp2_2/main.cpp.tpl</file>
+ <file>wizards/qsrapp2_2/main.qml.tpl</file>
+ <file>wizards/qsrapp2_2/qml.qrc.tpl</file>
+ <file>wizards/qsrapp2_2/safeasset.qrc.tpl</file>
+ <file>wizards/qsrapp2_2/wizard.json</file>
</qresource>
</RCC>
diff --git a/src/plugins/saferenderer/wizards/qsrapp2_1/CMakeLists.txt b/src/plugins/saferenderer/wizards/qsrapp2_1/CMakeLists.txt
index e17daccd9c1..336e251c5a2 100644
--- a/src/plugins/saferenderer/wizards/qsrapp2_1/CMakeLists.txt
+++ b/src/plugins/saferenderer/wizards/qsrapp2_1/CMakeLists.txt
@@ -61,6 +61,11 @@ else()
message(STATUS "Project is not linked with Qt when building for embedded systems.")
endif()
+install(TARGETS %{CMakeProjectName}
+ BUNDLE DESTINATION .
+ RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
+)
+
target_link_libraries(%{CMakeProjectName} PUBLIC
Qt::SafeRenderer
Qt::SafePlatformAdaptation
diff --git a/src/plugins/saferenderer/wizards/qsrapp2_1/main.cpp.tpl b/src/plugins/saferenderer/wizards/qsrapp2_1/main.cpp.tpl
index 80b45e04bb9..ac629c4ce6b 100644
--- a/src/plugins/saferenderer/wizards/qsrapp2_1/main.cpp.tpl
+++ b/src/plugins/saferenderer/wizards/qsrapp2_1/main.cpp.tpl
@@ -1,7 +1,4 @@
%{Cpp:LicenseTemplate}\
-%{JS: QtSupport.qtIncludes([ 'QtCore/QCoreApplication' ],
- [ 'QtCore/QCoreApplication' ]) }\
-
#include <QtSafeRenderer/qsafelayout.h>
#include <QtSafeRenderer/qsafelayoutresourcereader.h>
#include <QtSafeRenderer/statemanager.h>
@@ -22,8 +19,8 @@
int main(int argc, char *argv[])
{
- Q_UNUSED(argc);
- Q_UNUSED(argv);
+ (void)argc;
+ (void)argv;
static SafeRenderer::QSafeLayoutResourceReader layout("/layoutData/main/main.srl");
diff --git a/src/plugins/saferenderer/wizards/qsrapp2_1/wizard.json b/src/plugins/saferenderer/wizards/qsrapp2_1/wizard.json
index ff0c0ab2240..0ce260b2f91 100644
--- a/src/plugins/saferenderer/wizards/qsrapp2_1/wizard.json
+++ b/src/plugins/saferenderer/wizards/qsrapp2_1/wizard.json
@@ -3,7 +3,7 @@
"supportedProjectTypes": [ "Qt4ProjectManager.Qt4Project", "CMakeProjectManager.CMakeProject" ],
"id": "E.QSRApp2_1",
"category": "D.QtSafeRendererApplication",
- "trDescription": "Creates a Qt Safe Renderer 2.1 (and newer) project with a simple UI and project setup.\n\nSupports both qmake and CMake.",
+ "trDescription": "Creates a Qt Safe Renderer 2.1 project with a simple UI and project setup.\n\nSupports both qmake and CMake.",
"trDisplayName": "Qt Safe Renderer Application 2.1",
"trDisplayCategory": "Application (Qt Safe Renderer)",
"icon": "../icon.png",
diff --git a/src/plugins/saferenderer/wizards/qsrapp2_2/CMakeLists.txt b/src/plugins/saferenderer/wizards/qsrapp2_2/CMakeLists.txt
new file mode 100644
index 00000000000..336e251c5a2
--- /dev/null
+++ b/src/plugins/saferenderer/wizards/qsrapp2_2/CMakeLists.txt
@@ -0,0 +1,72 @@
+cmake_minimum_required(VERSION 3.16)
+project(%{CMakeProjectName} LANGUAGES CXX)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(CMAKE_AUTOMOC ON)
+
+# Define the condition for HOST_BUILD
+set(HOST_BUILD OFF) # Default to OFF
+
+if (NOT CMAKE_CROSSCOMPILING AND (NOT UNIX OR NOT (CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "arm|aarch64") OR APPLE))
+ set(HOST_BUILD ON)
+endif()
+
+find_package(Qt6 REQUIRED COMPONENTS Core Qml Quick SafeRenderer SafeRendererTools SafePlatformAdaptation)
+
+set(sources main.cpp
+)
+
+set (safeqmls
+"main.qml"
+)
+
+# Resource files are passed to qtsafelayouttool
+set(resource_files
+ "qml.qrc"
+)
+
+#resource.bin is loaded by qtsafelayouttool to find the resource data asset.
+qt6_add_binary_resources(resources_%{CMakeProjectName} ${resource_files} DESTINATION resource.bin)
+qsr_add_safelayout(generatelayout_%{CMakeProjectName} SAFE_QMLS ${safeqmls}
+ OUTPUT_PATH ${CMAKE_CURRENT_LIST_DIR}/layoutData
+ SAFE_RESOURCE "${CMAKE_CURRENT_LIST_DIR}/safeasset.qrc"
+ INPUT_RESOURCES resource.bin)
+qsr_add_resource(buildresource_%{CMakeProjectName} sources "${CMAKE_CURRENT_LIST_DIR}/safeasset.qrc")
+
+if (HOST_BUILD)
+ qt6_add_resources(sources ${resource_files})
+endif()
+
+add_executable(%{CMakeProjectName} WIN32 MACOSX_BUNDLE
+ ${sources}
+)
+
+#Enable when using monitor feature:
+#target_compile_definitions(%{CMakeProjectName} PRIVATE USE_OUTPUTVERIFIER)
+
+add_dependencies(%{CMakeProjectName} generatelayout_%{CMakeProjectName})
+
+if (HOST_BUILD)
+ target_compile_definitions(%{CMakeProjectName} PUBLIC
+ HOST_BUILD
+ )
+
+ target_link_libraries(%{CMakeProjectName} PUBLIC
+ Qt::Quick
+ Qt::Widgets
+ Qt::Qml
+ )
+else()
+ message(STATUS "Project is not linked with Qt when building for embedded systems.")
+endif()
+
+install(TARGETS %{CMakeProjectName}
+ BUNDLE DESTINATION .
+ RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
+)
+
+target_link_libraries(%{CMakeProjectName} PUBLIC
+ Qt::SafeRenderer
+ Qt::SafePlatformAdaptation
+)
diff --git a/src/plugins/saferenderer/wizards/qsrapp2_2/file.pro b/src/plugins/saferenderer/wizards/qsrapp2_2/file.pro
new file mode 100644
index 00000000000..6233d49b9cc
--- /dev/null
+++ b/src/plugins/saferenderer/wizards/qsrapp2_2/file.pro
@@ -0,0 +1,46 @@
+QT = qtsaferenderer qsrplatformadaptation
+
+CONFIG += c++17
+
+# You can make your code fail to compile if it uses deprecated APIs.
+# In order to do so, uncomment the following line.
+#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
+
+SOURCES += \\
+ %{CppFileName}
+
+
+# List of language codes that your application supports. For example, SAFE_LANGUAGES = en fi.
+#SAFE_LANGUAGES = en
+
+# List of translation file names excluding the language code. For example, SAFE_TRANSLATION = $$PWD/safeui.
+#SAFE_TRANSLATION = $$PWD/safeui
+
+# List of translation file names including the language code. There must be one file
+# for each language listed in SAFE_LANGUAGES. For example, TRANSLATIONS += safeui_en.ts safeui_fi.ts.
+#TRANSLATIONS += safeui_en.ts
+
+# You can use an lupdate_only{...} conditional statement to specify the QML files that contain texts.
+#lupdate_only {
+# SOURCES += main.qml
+#}
+
+
+RESOURCES += qml.qrc
+
+# Additional import path used to resolve QML modules in Qt Creator's code model
+QML_IMPORT_PATH = $$PWD/imports
+
+# Additional import path used to resolve QML modules just for Qt Quick Designer
+QML_DESIGNER_IMPORT_PATH =
+
+
+CONFIG += qtsaferenderer exceptions
+SAFE_QML = $$PWD/main.qml
+SAFE_LAYOUT_PATH = $$PWD/layoutData
+SAFE_RESOURCES += safeasset.qrc
+
+!cross_compile: DEFINES += HOST_BUILD
+!cross_compile: QT += widgets quick svg
+
+DISTFILES += main.qml
diff --git a/src/plugins/saferenderer/wizards/qsrapp2_2/main.cpp.tpl b/src/plugins/saferenderer/wizards/qsrapp2_2/main.cpp.tpl
new file mode 100644
index 00000000000..ae85076086d
--- /dev/null
+++ b/src/plugins/saferenderer/wizards/qsrapp2_2/main.cpp.tpl
@@ -0,0 +1,59 @@
+%{Cpp:LicenseTemplate}\
+#include <QtSafeRenderer/qsafelayout.h>
+#include <QtSafeRenderer/qsafelayoutresourcereader.h>
+#include <QtSafeRenderer/statemanager.h>
+
+#if defined(HOST_BUILD)
+#include <QGuiApplication>
+#include <QQmlApplicationEngine>
+#include <QQmlContext>
+#endif
+
+#if defined(USE_OUTPUTVERIFIER)
+#include <outputverifier.h>
+#include <outputverifier_capi.h>
+#endif
+
+#include "safewindow.h"
+#include "eventhandler.h"
+
+int main(int argc, char *argv[])
+{
+ (void)argc;
+ (void)argv;
+
+ static SafeRenderer::QSafeLayoutResourceReader layout("/layoutData/main/main.srl");
+
+ SafeRenderer::SafeWindow telltaleWindow(layout.size(), SafeRenderer::QSafePoint(0U, 0U));
+
+#if defined(USE_OUTPUTVERIFIER)
+ SafeRenderer::OutputVerifier &outputVerifier = SafeRenderer::OutputVerifier::getOutputVerifierInstance();
+ OutputVerifier_initVerifierDevice(0, 0, layout.size().width(), layout.size().height());
+#endif
+
+ static SafeRenderer::StateManager stateManager(telltaleWindow, layout);
+ telltaleWindow.requestUpdate(); //Request is required because eventHandler is not running yet.
+
+#if defined(USE_OUTPUTVERIFIER)
+ SafeRenderer::EventHandler msgHandler(stateManager, telltaleWindow, outputVerifier);
+#else
+ SafeRenderer::EventHandler msgHandler(stateManager, telltaleWindow);
+#endif
+
+#if defined(HOST_BUILD)
+ //Mixing the Qt and Qt Safe Renderer renderers is done here only for demonstration purposes on host, not for production purposes of any kind.
+ QQmlApplicationEngine engine;
+ const QUrl url(QStringLiteral("qrc:/main.qml"));
+ QObject::connect(&engine, &QQmlApplicationEngine::objectCreated, qApp,
+ [url](QObject *obj, const QUrl &objUrl) {
+ if (!obj && url == objUrl)
+ qDebug() << "Failed to start the main.qml";
+ }, Qt::QueuedConnection);
+ engine.addImportPath(":/imports");
+ engine.load(url);
+#endif
+
+ msgHandler.handleEvents();
+
+ return 0;
+}
diff --git a/src/plugins/saferenderer/wizards/qsrapp2_2/main.qml.tpl b/src/plugins/saferenderer/wizards/qsrapp2_2/main.qml.tpl
new file mode 100644
index 00000000000..115a6dcd4b5
--- /dev/null
+++ b/src/plugins/saferenderer/wizards/qsrapp2_2/main.qml.tpl
@@ -0,0 +1,25 @@
+import Qt.SafeRenderer
+import QtQuick.Window
+
+Window {
+ id: window
+ width: 640
+ height: 480
+ visible: true
+ title: qsTr("Hello QSR")
+
+ SafeText {
+ id: safeText
+ objectName: "safetextitem"
+ x: 206
+ y: 208
+ width: 380
+ height: 50
+ color: "#8ae234"
+ fillColor: "black"
+ text: "Hello Qt Safe Renderer!"
+ font.family: "Arial"
+ horizontalAlignment: Text.AlignLeft
+ font.pixelSize: 32
+ }
+}
diff --git a/src/plugins/saferenderer/wizards/qsrapp2_2/qml.qrc.tpl b/src/plugins/saferenderer/wizards/qsrapp2_2/qml.qrc.tpl
new file mode 100644
index 00000000000..5f6483ac33f
--- /dev/null
+++ b/src/plugins/saferenderer/wizards/qsrapp2_2/qml.qrc.tpl
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/">
+ <file>main.qml</file>
+ </qresource>
+</RCC>
diff --git a/src/plugins/saferenderer/wizards/qsrapp2_2/safeasset.qrc.tpl b/src/plugins/saferenderer/wizards/qsrapp2_2/safeasset.qrc.tpl
new file mode 100644
index 00000000000..601b61fc4c2
--- /dev/null
+++ b/src/plugins/saferenderer/wizards/qsrapp2_2/safeasset.qrc.tpl
@@ -0,0 +1,2 @@
+<!DOCTYPE RCC>
+<RCC/>
diff --git a/src/plugins/saferenderer/wizards/qsrapp2_2/wizard.json b/src/plugins/saferenderer/wizards/qsrapp2_2/wizard.json
new file mode 100644
index 00000000000..3be081525de
--- /dev/null
+++ b/src/plugins/saferenderer/wizards/qsrapp2_2/wizard.json
@@ -0,0 +1,115 @@
+{
+ "version": 1,
+ "supportedProjectTypes": [ "Qt4ProjectManager.Qt4Project", "CMakeProjectManager.CMakeProject" ],
+ "id": "E.QSRApp2_2",
+ "category": "D.QtSafeRendererApplication",
+ "trDescription": "Creates a Qt Safe Renderer 2.2 (and newer) project with a simple UI and project setup.\n\nSupports both qmake and CMake.",
+ "trDisplayName": "Qt Safe Renderer Application 2.2",
+ "trDisplayCategory": "Application (Qt Safe Renderer)",
+ "icon": "../icon.png",
+ "iconKind": "Themed",
+ "featuresRequired": [ "QtSupport.Wizards.FeatureQt" ],
+ "enabled": "%{JS: isAnyPluginRunning(['qmakeprojectmanager', 'cmakeprojectmanager'])}",
+
+ "options":
+ [
+ { "key": "ProjectFile", "value": "%{JS: value('BuildSystem') == 'qmake' ? value('ProFile') : value('CMakeFile')}" },
+ { "key": "CMakeProjectName", "value": "%{JS: value('ProjectName').replace(/-/g, '_')}" },
+ { "key": "ProFile", "value": "%{JS: Util.fileName(value('ProjectDirectory') + '/' + value('ProjectName'), 'pro')}" },
+ { "key": "CMakeFile", "value": "%{JS: Util.fileName(value('ProjectDirectory') + '/CMakeLists.txt')}" },
+ { "key": "HasTranslation", "value": "%{JS: value('TsFileName') !== ''}" },
+ { "key": "CppFileName", "value": "%{JS: 'main.' + Util.preferredSuffix('text/x-c++src')}" }
+ ],
+
+ "pages":
+ [
+ {
+ "trDisplayName": "Project Location",
+ "trShortTitle": "Location",
+ "typeId": "Project",
+ "data": { "trDescription": "This wizard creates a simple Qt Safe Renderer application." }
+ },
+ {
+ "trDisplayName": "Define Build System",
+ "trShortTitle": "Build System",
+ "typeId": "Fields",
+ "skipForSubprojects": true,
+ "data":
+ [
+ {
+ "name": "BuildSystem",
+ "trDisplayName": "Build system:",
+ "type": "ComboBox",
+ "persistenceKey": "BuildSystemType",
+ "data":
+ {
+ "index": 1,
+ "items":
+ [
+ {
+ "trKey": "qmake",
+ "value": "qmake",
+ "condition": "%{JS: isPluginRunning('qmakeprojectmanager')}"
+ },
+ {
+ "trKey": "cmake",
+ "value": "cmake",
+ "condition": "%{JS: isPluginRunning('cmakeprojectmanager')}"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "trDisplayName": "Kit Selection",
+ "trShortTitle": "Kits",
+ "typeId": "Kits",
+ "data": { "projectFilePath": "%{ProjectFile}" }
+ },
+ {
+ "trDisplayName": "Project Management",
+ "trShortTitle": "Summary",
+ "typeId": "Summary"
+ }
+ ],
+ "generators":
+ [
+ {
+ "typeId": "File",
+ "data":
+ [
+ {
+ "source": "file.pro",
+ "target": "%{ProFile}",
+ "openAsProject": true,
+ "condition": "%{JS: value('BuildSystem') === 'qmake'}"
+ },
+ {
+ "source": "CMakeLists.txt",
+ "target": "%{CMakeFile}",
+ "openAsProject": true,
+ "condition": "%{JS: value('BuildSystem') === 'cmake'}"
+ },
+ {
+ "source": "main.cpp.tpl",
+ "target": "%{CppFileName}",
+ "openInEditor": false
+ },
+ {
+ "source": "safeasset.qrc.tpl",
+ "target": "safeasset.qrc"
+ },
+ {
+ "source": "qml.qrc.tpl",
+ "target": "qml.qrc"
+ },
+ {
+ "source": "main.qml.tpl",
+ "target": "main.qml",
+ "openInEditor": true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/manual/widgets/components/tst_manual_widgets_components.cpp b/tests/manual/widgets/components/tst_manual_widgets_components.cpp
index ab322d8eded..0fe69665b35 100644
--- a/tests/manual/widgets/components/tst_manual_widgets_components.cpp
+++ b/tests/manual/widgets/components/tst_manual_widgets_components.cpp
@@ -41,7 +41,10 @@ QWidget *widgets()
switchOff->setLayoutDirection(Qt::LeftToRight);
auto tabBar = new QtcTabBar;
- tabBar->addTab("Tab number 1");
+ tabBar->setExpanding(false);
+ tabBar->setMovable(true);
+ tabBar->setTabsClosable(true);
+ tabBar->addTab("Tab 1");
tabBar->addTab("2");
tabBar->addTab("3");