From 4e2d8d02260f74bcd4c0196cc4e0fdecf2669179 Mon Sep 17 00:00:00 2001 From: hjk Date: Fri, 7 Jun 2024 08:57:42 +0200 Subject: [PATCH 01/24] Fix more metatype related deprecation warnings Change-Id: If206b70d263bcdb6d617827fb9cb8fe3214564a1 Reviewed-by: Christian Stenger Reviewed-by: Mahmoud Badri --- src/plugins/debugger/qml/qmlengine.cpp | 2 +- src/plugins/effectcomposer/effectcomposercontextobject.cpp | 4 ++-- src/plugins/mcusupport/mcukitaspect.cpp | 4 ++-- src/plugins/projectexplorer/kitaspects.cpp | 4 ++-- .../materialeditor/materialeditorcontextobject.cpp | 4 ++-- .../propertyeditor/propertyeditorcontextobject.cpp | 4 ++-- .../components/textureeditor/textureeditorcontextobject.cpp | 4 ++-- .../components/timelineeditor/timelinepropertyitem.cpp | 6 +++--- .../qmldesigner/designercore/model/texttomodelmerger.cpp | 2 +- 9 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/plugins/debugger/qml/qmlengine.cpp b/src/plugins/debugger/qml/qmlengine.cpp index c214926ec48..489aaae7900 100644 --- a/src/plugins/debugger/qml/qmlengine.cpp +++ b/src/plugins/debugger/qml/qmlengine.cpp @@ -904,7 +904,7 @@ static ConsoleItem *constructLogItemTree(const QVariant &result, const QString & if (child) item->appendChild(child); } - } else if (result.canConvert(QMetaType::QString)) { + } else if (result.canConvert(QMetaType(QMetaType::QString))) { item = new ConsoleItem(ConsoleItem::DefaultType, result.toString()); } else { item = new ConsoleItem(ConsoleItem::DefaultType, "Unknown Value"); diff --git a/src/plugins/effectcomposer/effectcomposercontextobject.cpp b/src/plugins/effectcomposer/effectcomposercontextobject.cpp index dd42092e72e..95ebe7a3670 100644 --- a/src/plugins/effectcomposer/effectcomposercontextobject.cpp +++ b/src/plugins/effectcomposer/effectcomposercontextobject.cpp @@ -39,9 +39,9 @@ QString EffectComposerContextObject::convertColorToString(const QVariant &color) { QString colorString; QColor theColor; - if (color.canConvert(QVariant::Color)) { + if (color.canConvert(QMetaType(QMetaType::QColor))) { theColor = color.value(); - } else if (color.canConvert(QVariant::Vector3D)) { + } else if (color.canConvert(QMetaType(QMetaType::QVector3D))) { auto vec = color.value(); theColor = QColor::fromRgbF(vec.x(), vec.y(), vec.z()); } diff --git a/src/plugins/mcusupport/mcukitaspect.cpp b/src/plugins/mcusupport/mcukitaspect.cpp index 1ab803b2437..7e75288b4f9 100644 --- a/src/plugins/mcusupport/mcukitaspect.cpp +++ b/src/plugins/mcusupport/mcukitaspect.cpp @@ -78,7 +78,7 @@ public: const QVariant checkFormat = kit->value(McuDependenciesKitAspect::id()); if (!checkFormat.isValid() || checkFormat.isNull()) return result; - if (!checkFormat.canConvert(QMetaType::QVariantList)) + if (!checkFormat.canConvert(QMetaType(QMetaType::QVariantList))) return {BuildSystemTask(Task::Error, Tr::tr("The MCU dependencies setting value is invalid."))}; // check paths defined in cmake variables for given dependencies exist @@ -105,7 +105,7 @@ public: QTC_ASSERT(kit, return ); const QVariant variant = kit->value(McuDependenciesKitAspect::id()); - if (!variant.isNull() && !variant.canConvert(QMetaType::QVariantList)) { + if (!variant.isNull() && !variant.canConvert(QMetaType(QMetaType::QVariantList))) { qWarning("Kit \"%s\" has a wrong mcu dependencies value set.", qPrintable(kit->displayName())); McuDependenciesKitAspect::setDependencies(kit, Utils::EnvironmentItems()); diff --git a/src/plugins/projectexplorer/kitaspects.cpp b/src/plugins/projectexplorer/kitaspects.cpp index db3300f3270..35193cf6e90 100644 --- a/src/plugins/projectexplorer/kitaspects.cpp +++ b/src/plugins/projectexplorer/kitaspects.cpp @@ -1539,7 +1539,7 @@ Tasks EnvironmentKitAspectFactory::validate(const Kit *k) const QTC_ASSERT(k, return result); const QVariant variant = k->value(EnvironmentKitAspect::id()); - if (!variant.isNull() && !variant.canConvert(QMetaType::QVariantList)) + if (!variant.isNull() && !variant.canConvert(QMetaType(QMetaType::QVariantList))) result << BuildSystemTask(Task::Error, Tr::tr("The environment setting value is invalid.")); return result; @@ -1550,7 +1550,7 @@ void EnvironmentKitAspectFactory::fix(Kit *k) QTC_ASSERT(k, return); const QVariant variant = k->value(EnvironmentKitAspect::id()); - if (!variant.isNull() && !variant.canConvert(QMetaType::QVariantList)) { + if (!variant.isNull() && !variant.canConvert(QMetaType(QMetaType::QVariantList))) { qWarning("Kit \"%s\" has a wrong environment value set.", qPrintable(k->displayName())); EnvironmentKitAspect::setEnvironmentChanges(k, EnvironmentItems()); } diff --git a/src/plugins/qmldesigner/components/materialeditor/materialeditorcontextobject.cpp b/src/plugins/qmldesigner/components/materialeditor/materialeditorcontextobject.cpp index 664006fb7a5..f583498db78 100644 --- a/src/plugins/qmldesigner/components/materialeditor/materialeditorcontextobject.cpp +++ b/src/plugins/qmldesigner/components/materialeditor/materialeditorcontextobject.cpp @@ -46,9 +46,9 @@ QString MaterialEditorContextObject::convertColorToString(const QVariant &color) { QString colorString; QColor theColor; - if (color.canConvert(QVariant::Color)) { + if (color.canConvert(QMetaType(QMetaType::QColor))) { theColor = color.value(); - } else if (color.canConvert(QVariant::Vector3D)) { + } else if (color.canConvert(QMetaType(QMetaType::QVector3D))) { auto vec = color.value(); theColor = QColor::fromRgbF(vec.x(), vec.y(), vec.z()); } diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorcontextobject.cpp b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorcontextobject.cpp index b6d119a4248..1a49ce0c39e 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorcontextobject.cpp +++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorcontextobject.cpp @@ -87,9 +87,9 @@ QString PropertyEditorContextObject::convertColorToString(const QVariant &color) { QString colorString; QColor theColor; - if (color.canConvert(QVariant::Color)) { + if (color.canConvert(QMetaType(QMetaType::QColor))) { theColor = color.value(); - } else if (color.canConvert(QVariant::Vector3D)) { + } else if (color.canConvert(QMetaType(QMetaType::QVector3D))) { auto vec = color.value(); theColor = QColor::fromRgbF(vec.x(), vec.y(), vec.z()); } diff --git a/src/plugins/qmldesigner/components/textureeditor/textureeditorcontextobject.cpp b/src/plugins/qmldesigner/components/textureeditor/textureeditorcontextobject.cpp index 73e784846bb..30f276a48db 100644 --- a/src/plugins/qmldesigner/components/textureeditor/textureeditorcontextobject.cpp +++ b/src/plugins/qmldesigner/components/textureeditor/textureeditorcontextobject.cpp @@ -47,9 +47,9 @@ QString TextureEditorContextObject::convertColorToString(const QVariant &color) { QString colorString; QColor theColor; - if (color.canConvert(QVariant::Color)) { + if (color.canConvert(QMetaType(QMetaType::QColor))) { theColor = color.value(); - } else if (color.canConvert(QVariant::Vector3D)) { + } else if (color.canConvert(QMetaType(QMetaType::QVector3D))) { auto vec = color.value(); theColor = QColor::fromRgbF(vec.x(), vec.y(), vec.z()); } diff --git a/src/plugins/qmldesigner/components/timelineeditor/timelinepropertyitem.cpp b/src/plugins/qmldesigner/components/timelineeditor/timelinepropertyitem.cpp index 762bd85c8b4..04cc8ebebc6 100644 --- a/src/plugins/qmldesigner/components/timelineeditor/timelinepropertyitem.cpp +++ b/src/plugins/qmldesigner/components/timelineeditor/timelinepropertyitem.cpp @@ -107,14 +107,14 @@ static void editValue(const ModelNode &frameNode, const std::pair int userType = value.typeId(); QVariant newValue = dialog->value(); - if (newValue.canConvert(userType)) { + if (newValue.canConvert(QMetaType(userType))) { QVariant newValueConverted = newValue; - bool converted = newValueConverted.convert(userType); + bool converted = newValueConverted.convert(QMetaType(userType)); if (!converted) { // convert() fails for int to double, so we try this combination newValueConverted = newValue; - converted = newValueConverted.convert(QMetaType::Double); + converted = newValueConverted.convert(QMetaType(QMetaType::Double)); } if (converted) diff --git a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp index b66270dca12..ded7fbc5ef4 100644 --- a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp +++ b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp @@ -1565,7 +1565,7 @@ void TextToModelMerger::syncVariantProperty(AbstractProperty &modelProperty, const TypeName &astType, DifferenceHandler &differenceHandler) { - if (astValue.canConvert(QMetaType::QString)) + if (astValue.canConvert(QMetaType(QMetaType::QString))) populateQrcMapping(astValue.toString()); if (modelProperty.isVariantProperty()) { From 2d35dd1532d4b5952802a5573ec4d45cb77e80d7 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Fri, 7 Jun 2024 17:07:48 +0200 Subject: [PATCH 02/24] ClangTools: Fix behavior of expand/collapse button It's a check button, so it should behave like one, i.e. its current state should be considered when adding new diagnostics, and it should be enabled regardless of whether any diagnostics are currently visible. Change-Id: I0e21ad5fdc5cd6a20fda7b40ea7eecd454d1e11f Reviewed-by: David Schulz --- src/plugins/clangtools/clangtool.cpp | 37 ++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/src/plugins/clangtools/clangtool.cpp b/src/plugins/clangtools/clangtool.cpp index 21b5ea6fbdc..20ba1328cb5 100644 --- a/src/plugins/clangtools/clangtool.cpp +++ b/src/plugins/clangtools/clangtool.cpp @@ -474,11 +474,10 @@ ClangTool::ClangTool(const QString &name, Id id, ClangToolType type) // Expand/Collapse action = new QAction(this); - action->setDisabled(true); action->setCheckable(true); action->setIcon(Utils::Icons::EXPAND_ALL_TOOLBAR.icon()); - action->setToolTip(Tr::tr("Expand All")); - connect(action, &QAction::toggled, this, [this](bool checked){ + m_expandCollapse = action; + const auto handleCollapseExpandToggled = [this](bool checked){ if (checked) { m_expandCollapse->setToolTip(Tr::tr("Collapse All")); m_diagnosticView->expandAll(); @@ -486,8 +485,9 @@ ClangTool::ClangTool(const QString &name, Id id, ClangToolType type) m_expandCollapse->setToolTip(Tr::tr("Expand All")); m_diagnosticView->collapseAll(); } - }); - m_expandCollapse = action; + }; + connect(action, &QAction::toggled, this, handleCollapseExpandToggled); + handleCollapseExpandToggled(action->isChecked()); // Filter button action = m_showFilter = new QAction(this); @@ -1242,8 +1242,32 @@ QSet ClangTool::diagnostics() const void ClangTool::onNewDiagnosticsAvailable(const Diagnostics &diagnostics, bool generateMarks) { - QTC_ASSERT(m_diagnosticModel, return); + const int oldLevel1RowCount = m_diagnosticModel->rowCount(); + const auto getOldLastLevel1Index = [&] { + return m_diagnosticModel->index(oldLevel1RowCount - 1, 0); + }; + const auto getLevel2RowCountForOldLastLevel1Index = [&] { + return oldLevel1RowCount == 0 ? -1 : m_diagnosticModel->rowCount(getOldLastLevel1Index()); + }; + const int oldLevel2RowCount = getLevel2RowCountForOldLastLevel1Index(); m_diagnosticModel->addDiagnostics(diagnostics, generateMarks); + if (!m_expandCollapse->isChecked()) + return; + + // Now expand newly added items, both in existing file nodes and in newly added ones. + // We assume diagnostics arrive "in order", i.e. things are only ever added at the end + // (in the source model). + const int newLevel2RowCount = getLevel2RowCountForOldLastLevel1Index(); + for (int i = oldLevel2RowCount; i < newLevel2RowCount; ++i) { + m_diagnosticView->expand(m_diagnosticFilterModel->mapFromSource( + m_diagnosticModel + ->index(i, 0, m_diagnosticFilterModel->mapFromSource(getOldLastLevel1Index())))); + } + const int newLevel1RowCount = m_diagnosticFilterModel->rowCount(); + for (int i = oldLevel1RowCount; i < newLevel1RowCount; ++i) { + m_diagnosticView->expandRecursively( + m_diagnosticFilterModel->mapFromSource(m_diagnosticModel->index(i, 0))); + } } void ClangTool::updateForCurrentState() @@ -1273,7 +1297,6 @@ void ClangTool::updateForCurrentState() m_goBack->setEnabled(issuesVisible > 0); m_goNext->setEnabled(issuesVisible > 0); m_clear->setEnabled(!isRunning); - m_expandCollapse->setEnabled(issuesVisible); m_loadExported->setEnabled(!isRunning); m_showFilter->setEnabled(issuesFound > 1); From b66a80004515ed29dc84345d3ec4e543247748ae Mon Sep 17 00:00:00 2001 From: Cristian Adam Date: Mon, 10 Jun 2024 13:48:23 +0000 Subject: [PATCH 03/24] Revert "CMakePM: Set platform codegen and linker flags for GCC compilers" This reverts commit 831b93905bf291d315c76e0692445cf5d39b9b08. Reason for revert: breaks Android and it looks like magic. For CMake one should use a toolchain file. But this revert keeps the CMAKE_C| XX_FLAGS_INIT parameters update / merging. Change-Id: I1c3c61e4a9345a29e72db7f5f5a2d6e3fdba52f1 Reviewed-by: hjk Reviewed-by: Alessandro Portale --- .../cmakebuildconfiguration.cpp | 27 +------------------ 1 file changed, 1 insertion(+), 26 deletions(-) diff --git a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp index 696ce44c1e2..fed2112822e 100644 --- a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp +++ b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp @@ -34,7 +34,6 @@ #include #include #include -#include #include #include #include @@ -1184,30 +1183,6 @@ static CommandLine defaultInitialCMakeCommand( } } - // GCC compiler and linker specific flags - for (Toolchain *tc : ToolchainKitAspect::toolChains(k)) { - if (auto *gccTc = tc->asGccToolchain()) { - const QStringList compilerFlags = gccTc->platformCodeGenFlags(); - - QLatin1String languageFlagsInit; - if (gccTc->language() == ProjectExplorer::Constants::C_LANGUAGE_ID) - languageFlagsInit = QLatin1String(CMAKE_C_FLAGS_INIT); - else if (gccTc->language() == ProjectExplorer::Constants::CXX_LANGUAGE_ID) - languageFlagsInit = QLatin1String(CMAKE_CXX_FLAGS_INIT); - - if (!languageFlagsInit.isEmpty() && !compilerFlags.isEmpty()) - cmd.addArg("-D" + languageFlagsInit + ":STRING=" + compilerFlags.join(" ")); - - const QStringList linkerFlags = gccTc->platformLinkerFlags(); - if (!linkerFlags.isEmpty()) { - const QString joinedLinkerFlags = linkerFlags.join(" "); - cmd.addArg("-DCMAKE_EXE_LINKER_FLAGS_INIT:STRING=" + joinedLinkerFlags); - cmd.addArg("-DCMAKE_MODULE_LINKER_FLAGS_INIT:STRING=" + joinedLinkerFlags); - cmd.addArg("-DCMAKE_SHARED_LINKER_FLAGS_INIT:STRING=" + joinedLinkerFlags); - } - } - } - cmd.addArgs(CMakeConfigurationKitAspect::toArgumentsList(k)); cmd.addArgs(CMakeConfigurationKitAspect::additionalConfiguration(k), CommandLine::Raw); @@ -1356,7 +1331,7 @@ static void addCMakeConfigurePresetToInitialArguments(QStringList &initialArgume if (argFilePath != presetFilePath) arg = presetItem.toArgument(); - } else if (argItem.key == CMAKE_CXX_FLAGS_INIT) { + } else if (argItem.key == CMAKE_C_FLAGS_INIT || argItem.key == CMAKE_CXX_FLAGS_INIT) { // Append the preset value with at the initial parameters value (e.g. QML Debugging) if (argItem.expandedValue(k) != QString::fromUtf8(presetItem.value)) { argItem.value.append(" "); From dbe2e422f7fb17b6f25bc2a8c7dcd8c5127fb672 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Mon, 27 May 2024 14:45:24 +0200 Subject: [PATCH 04/24] Axivion: Link from dashboard overview to table Make issue counts clickable and directly jump to the respective issue kind. This approach mimics original dashboard view more closer and avoids confusion on the user side when trying to find the issue table. Change-Id: Ic23368ea6d881b46950ef41c28d4cbf737163cf2 Reviewed-by: Jarek Kobus --- src/plugins/axivion/axivionoutputpane.cpp | 70 ++++++++++++++++++----- 1 file changed, 55 insertions(+), 15 deletions(-) diff --git a/src/plugins/axivion/axivionoutputpane.cpp b/src/plugins/axivion/axivionoutputpane.cpp index 80dd5103c14..d3043a12751 100644 --- a/src/plugins/axivion/axivionoutputpane.cpp +++ b/src/plugins/axivion/axivionoutputpane.cpp @@ -51,6 +51,8 @@ using namespace Utils; namespace Axivion::Internal { +void showIssuesFromDashboard(const QString &kind); // impl at bottom + class DashboardWidget : public QScrollArea { public: @@ -147,14 +149,24 @@ void DashboardWidget::updateUi() } return prefix; }; - auto addValuesWidgets = [this, &toolTip](const QString &issueKind, qint64 total, qint64 added, qint64 removed, int row) { + auto linked = [this](const QString &text, const QString &href, bool link) { + return link ? QString("%2").arg(href).arg(text) + : text; + }; + auto addValuesWidgets = [this, &toolTip, &linked](const QString &issueKind, qint64 total, + qint64 added, qint64 removed, int row, bool link) { const QString currentToolTip = toolTip(issueKind); QLabel *label = new QLabel(issueKind, this); label->setToolTip(currentToolTip); m_gridLayout->addWidget(label, row, 0); - label = new QLabel(QString::number(total), this); + label = new QLabel(linked(QString::number(total), issueKind, link), this); label->setToolTip(currentToolTip); label->setAlignment(Qt::AlignRight); + if (link) { + connect(label, &QLabel::linkActivated, this, [](const QString &issueKind) { + showIssuesFromDashboard(issueKind); + }); + } m_gridLayout->addWidget(label, row, 1); label = new QLabel(this); label->setPixmap(trendIcon(added, removed)); @@ -190,12 +202,12 @@ void DashboardWidget::updateUi() allAdded += added; qint64 removed = extract_value(counts, QStringLiteral("Removed")); allRemoved += removed; - addValuesWidgets(issueCount.first, total, added, removed, row); + addValuesWidgets(issueCount.first, total, added, removed, row, true); ++row; } } } - addValuesWidgets(Tr::tr("Total:"), allTotal, allAdded, allRemoved, row); + addValuesWidgets(Tr::tr("Total:"), allTotal, allAdded, allRemoved, row, false); } struct LinkWithColumns @@ -263,7 +275,7 @@ class IssuesWidget : public QScrollArea { public: explicit IssuesWidget(QWidget *parent = nullptr); - void updateUi(); + void updateUi(const QString &kind); const std::optional currentTableInfo() const { return m_currentTableInfo; } IssueListSearch searchFromUi() const; @@ -378,7 +390,7 @@ IssuesWidget::IssuesWidget(QWidget *parent) setWidgetResizable(true); } -void IssuesWidget::updateUi() +void IssuesWidget::updateUi(const QString &kind) { setFiltersEnabled(false); const std::optional projectInfo = Internal::projectInfo(); @@ -392,11 +404,30 @@ void IssuesWidget::updateUi() setFiltersEnabled(true); // avoid refetching existing data - if (!m_currentPrefix.isEmpty() || m_issuesModel->rowCount()) + if (kind.isEmpty() && (!m_currentPrefix.isEmpty() || m_issuesModel->rowCount())) return; - if (info.issueKinds.size()) - m_currentPrefix = info.issueKinds.front().prefix; + if (!kind.isEmpty()) { + const int index + = Utils::indexOf( info.issueKinds, [kind](const Dto::IssueKindInfoDto &dto) { + return dto.prefix == kind; }); + if (index != -1) { + m_currentPrefix = kind; + auto kindButton = m_typesButtonGroup->button(index + 1); + if (QTC_GUARD(kindButton)) + kindButton->setChecked(true); + // reset filters - if kind is not empty we get triggered from dashboard overview + if (!m_userNames.isEmpty()) + m_ownerFilter->setCurrentIndex(0); + m_pathGlobFilter->clear(); + if (m_versionDates.size() > 1) { + m_versionStart->setCurrentIndex(m_versionDates.count() - 1); + m_versionEnd->setCurrentIndex(0); + } + } + } + if (m_currentPrefix.isEmpty()) + m_currentPrefix = info.issueKinds.size() ? info.issueKinds.front().prefix : QString{}; fetchTable(); } @@ -767,12 +798,7 @@ public: m_showIssues->setIcon(Icons::ZOOM_TOOLBAR.icon()); m_showIssues->setToolTip(Tr::tr("Search for issues")); m_showIssues->setCheckable(true); - connect(m_showIssues, &QToolButton::clicked, this, [this] { - QTC_ASSERT(m_outputWidget, return); - m_outputWidget->setCurrentIndex(1); - if (auto issues = static_cast(m_outputWidget->widget(1))) - issues->updateUi(); - }); + connect(m_showIssues, &QToolButton::clicked, this, [this] { handleShowIssues({}); }); auto *butonGroup = new QButtonGroup(this); butonGroup->addButton(m_showDashboard); butonGroup->addButton(m_showIssues); @@ -814,6 +840,14 @@ public: void goToNext() final {} void goToPrev() final {} + void handleShowIssues(const QString &kind) + { + QTC_ASSERT(m_outputWidget, return); + m_outputWidget->setCurrentIndex(1); + if (auto issues = static_cast(m_outputWidget->widget(1))) + issues->updateUi(kind); + } + void updateDashboard() { if (auto dashboard = static_cast(m_outputWidget->widget(0))) { @@ -897,4 +931,10 @@ static bool issueListContextMenuEvent(const ItemViewEvent &ev) return theAxivionOutputPane->handleContextMenu(issue, ev); } +void showIssuesFromDashboard(const QString &kind) +{ + QTC_ASSERT(theAxivionOutputPane, return); + theAxivionOutputPane->handleShowIssues(kind); +} + } // Axivion::Internal From faf6ae04c2438f4a3f8c36a3c6f803aee1da3ef8 Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Mon, 10 Jun 2024 11:59:09 +0200 Subject: [PATCH 05/24] TaskTree: Qt-ify the code (part 3) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 11. Replace local lambda with static method, otherwise getting: "qarraydatapointer.h:110:17: error: pointer may be used after ‘void free(void*)’" on rhel-9.2-gcc12. 12. Use std::optional::reset() instead of "= {}", otherwise getting: "error: use of overloaded operator '=' is ambiguous (with operand types 'std::optional' and 'void')" on vxworks-imx6. Amends 88ee3aa90840e9c4fa13e79a29bbe9dba50d782b Amends 6621c68ca970c6760fbf10deae0a175202c6a8e1 Change-Id: Ie1631e119cb89d23a6acb3b4c39199e6ebaf1ea1 Reviewed-by: hjk --- src/libs/solutions/tasking/barrier.cpp | 2 +- src/libs/solutions/tasking/tasktree.cpp | 21 ++++++++++++--------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/libs/solutions/tasking/barrier.cpp b/src/libs/solutions/tasking/barrier.cpp index 650aae3403b..126d4f3b8a5 100644 --- a/src/libs/solutions/tasking/barrier.cpp +++ b/src/libs/solutions/tasking/barrier.cpp @@ -24,7 +24,7 @@ void Barrier::start() { QT_ASSERT(!isRunning(), return); m_current = 0; - m_result = {}; + m_result.reset(); } void Barrier::advance() diff --git a/src/libs/solutions/tasking/tasktree.cpp b/src/libs/solutions/tasking/tasktree.cpp index 2c7a5a8dedb..d923eb31d0e 100644 --- a/src/libs/solutions/tasking/tasktree.cpp +++ b/src/libs/solutions/tasking/tasktree.cpp @@ -1450,6 +1450,11 @@ ExecutableItem ExecutableItem::withTimeout(milliseconds timeout, static QString currentTime() { return QTime::currentTime().toString(Qt::ISODateWithMs); } +static QString logHeader(const QString &logName) +{ + return QString::fromLatin1("TASK TREE LOG [%1] \"%2\"").arg(currentTime(), logName); +}; + /*! Attaches a custom debug printout to a copy of \c this ExecutableItem, issued on task startup and after the task is finished, and returns the coupled item. @@ -1463,9 +1468,6 @@ static QString currentTime() { return QTime::currentTime().toString(Qt::ISODateW */ ExecutableItem ExecutableItem::withLog(const QString &logName) const { - const auto header = [logName] { - return QString::fromLatin1("TASK TREE LOG [%1] \"%2\"").arg(currentTime(), logName); - }; struct LogStorage { time_point start; @@ -1474,21 +1476,22 @@ ExecutableItem ExecutableItem::withLog(const QString &logName) const const Storage storage; return Group { storage, - onGroupSetup([storage, header] { + onGroupSetup([storage, logName] { storage->start = system_clock::now(); storage->asyncCount = activeTaskTree()->asyncCount(); - qDebug().noquote() << header() << "started."; + qDebug().noquote().nospace() << logHeader(logName) << " started."; }), *this, - onGroupDone([storage, header](DoneWith result) { + onGroupDone([storage, logName](DoneWith result) { const auto elapsed = duration_cast(system_clock::now() - storage->start); const int asyncCountDiff = activeTaskTree()->asyncCount() - storage->asyncCount; QT_CHECK(asyncCountDiff >= 0); const QMetaEnum doneWithEnum = QMetaEnum::fromType(); const QString syncType = asyncCountDiff ? QString::fromLatin1("asynchronously") : QString::fromLatin1("synchronously"); - qDebug().noquote().nospace() << header() << " finished " << syncType << " with " - << doneWithEnum.valueToKey(int(result)) << " within " << elapsed.count() << "ms."; + qDebug().noquote().nospace() << logHeader(logName) << " finished " << syncType + << " with " << doneWithEnum.valueToKey(int(result)) + << " within " << elapsed.count() << "ms."; }) }; } @@ -3383,7 +3386,7 @@ TimeoutTaskAdapter::~TimeoutTaskAdapter() void TimeoutTaskAdapter::start() { m_timerId = scheduleTimeout(*task(), this, [this] { - m_timerId = {}; + m_timerId.reset(); emit done(DoneResult::Success); }); } From a8ea6c1eac909148c95ec0c750756d94da1a7c09 Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 11 Jun 2024 11:07:54 +0200 Subject: [PATCH 06/24] Debugger: Fix action handling of QML Console filter buttons Amends 93a58039561b. Fixes: QTCREATORBUG-30788 Change-Id: I3699e07e67821098500b5b4f85a15d8b19f57ec5 Reviewed-by: Christian Stenger --- src/plugins/debugger/console/console.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/plugins/debugger/console/console.cpp b/src/plugins/debugger/console/console.cpp index b1ee0dac83e..d7f3cb23343 100644 --- a/src/plugins/debugger/console/console.cpp +++ b/src/plugins/debugger/console/console.cpp @@ -27,6 +27,8 @@ const char SHOW_LOG[] = "showLog"; const char SHOW_WARNING[] = "showWarning"; const char SHOW_ERROR[] = "showError"; +using namespace Utils; + namespace Debugger::Internal { ///////////////////////////////////////////////////////////////////// @@ -90,8 +92,8 @@ Console::Console() m_showDebug.setLabelText(Tr::tr("Show debug, log, and info messages.")); m_showDebug.setToolTip(Tr::tr("Show debug, log, and info messages.")); m_showDebug.setValue(true); - m_showDebug.action()->setIcon(Utils::Icons::INFO_TOOLBAR.icon()); - connect(&m_showDebug, &Utils::BoolAspect::changed, + m_showDebug.setIcon(Icons::INFO_TOOLBAR.icon()); + connect(&m_showDebug, &BoolAspect::changed, proxyModel, [this, proxyModel] { proxyModel->setShowLogs(m_showDebug()); }); m_showDebugButton->setDefaultAction(m_showDebug.action()); @@ -102,8 +104,8 @@ Console::Console() m_showWarning.setLabelText(Tr::tr("Show warning messages.")); m_showWarning.setToolTip(Tr::tr("Show warning messages.")); m_showWarning.setValue(true); - m_showWarning.action()->setIcon(Utils::Icons::WARNING_TOOLBAR.icon()); - connect(m_showWarning.action(), &QAction::toggled, + m_showWarning.setIcon(Icons::WARNING_TOOLBAR.icon()); + connect(&m_showWarning, &BoolAspect::changed, proxyModel, [this, proxyModel] { proxyModel->setShowWarnings(m_showWarning()); }); m_showWarningButton->setDefaultAction(m_showWarning.action()); @@ -114,8 +116,8 @@ Console::Console() m_showError.setLabelText(Tr::tr("Show error messages.")); m_showError.setToolTip(Tr::tr("Show error messages.")); m_showError.setValue(true); - m_showError.action()->setIcon(Utils::Icons::CRITICAL_TOOLBAR.icon()); - connect(m_showError.action(), &QAction::toggled, + m_showError.setIcon(Icons::CRITICAL_TOOLBAR.icon()); + connect(&m_showError, &BoolAspect::changed, proxyModel, [this, proxyModel] { proxyModel->setShowErrors(m_showError()); }); m_showErrorButton->setDefaultAction(m_showError.action()); From 3e40f2f0e4e5321a942a541d462ea29a07c49415 Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Tue, 11 Jun 2024 13:40:20 +0200 Subject: [PATCH 07/24] Doc: Add a note that Docker plugin needs to be enabled And a link to how to do it. Change-Id: I4c2ed3e64306629db39bdf085db973c04bbb65f2 Reviewed-by: Marcus Tillmanns --- doc/qtcreator/src/docker/creator-docker.qdoc | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/doc/qtcreator/src/docker/creator-docker.qdoc b/doc/qtcreator/src/docker/creator-docker.qdoc index 9524dcd5ec8..4f1167b359a 100644 --- a/doc/qtcreator/src/docker/creator-docker.qdoc +++ b/doc/qtcreator/src/docker/creator-docker.qdoc @@ -25,6 +25,8 @@ You are advised to use CMake to build applications in the Docker container. + \note Enable the Docker plugin to use it. + To pull images from Docker hub or other registries, use the \l{https://docs.docker.com/engine/reference/commandline/pull/}{docker pull} command. @@ -64,7 +66,8 @@ Go to \preferences > \uicontrol Kits to check that the automatically generated kits point to the appropriate kit items. - \sa {Docker}{How To: Develop for Docker}, {Manage Kits}{How To: Manage Kits} + \sa {Enable and disable plugins}, {Docker}{How To: Develop for Docker}, + {Manage Kits}{How To: Manage Kits} */ /*! @@ -75,6 +78,8 @@ \title Set preferences for Docker devices + \note Enable the Docker plugin to use it. + To set preferences for Docker devices: \list 1 @@ -165,7 +170,8 @@ \uicontrol {List Auto-Detected Kit Items}. To remove them, select \uicontrol {Remove Auto-Detected Kit Items}. - \sa {Docker}{How To: Develop for Docker}, {Manage Kits}{How To: Manage Kits} + \sa {Enable and disable plugins}, {Docker}{How To: Develop for Docker}, + {Manage Kits}{How To: Manage Kits} */ /*! @@ -176,6 +182,8 @@ \title Build for and run on Docker devices + \note Enable the Docker plugin to use it. + To specify build settings for Docker images: \list 1 @@ -188,5 +196,6 @@ Select \uicontrol Run to specify run settings. Usually, you can use the default settings. - \sa {Docker}{How To: Develop for Docker}, {Manage Kits}{How To: Manage Kits} + \sa {Enable and disable plugins}, {Docker}{How To: Develop for Docker}, + {Manage Kits}{How To: Manage Kits} */ From 3aee50f5fd9ebd46c70bed9b0e7343f90afb6603 Mon Sep 17 00:00:00 2001 From: hjk Date: Mon, 10 Jun 2024 15:16:02 +0200 Subject: [PATCH 08/24] Debugger: Paddle back on the (non-)auto detection of Qt versions It looks like there are Qt-using scenarios without easy way to have the right Qt version in the kit, Among the frequent cases where we need to distinguish Qt versions in the dumpers are the Qt5/6 container layout differences which can in some cases be detected from the currently dumped value. Use that now as the primary distinction and fall back to the previous expensive peeking only if that is needed. This also postpones any Qt version related activity until a real Qt type is encountered, i.e. does not impact non-Qt scenarios. Task-number: QTCREATORBUG-31033 Change-Id: I67b6e34c42994ad9f6e8ec8698b430b55327cf0c Reviewed-by: hjk Reviewed-by: David Schulz Reviewed-by: Christian Stenger --- share/qtcreator/debugger/cdbbridge.py | 4 +- share/qtcreator/debugger/dumper.py | 126 +++++++++++++++++------- share/qtcreator/debugger/gdbbridge.py | 30 ++++++ share/qtcreator/debugger/lldbbridge.py | 48 ++++++++++ share/qtcreator/debugger/qttypes.py | 128 +++++++++++++------------ 5 files changed, 237 insertions(+), 99 deletions(-) diff --git a/share/qtcreator/debugger/cdbbridge.py b/share/qtcreator/debugger/cdbbridge.py index c16467915a0..ce88c903a77 100644 --- a/share/qtcreator/debugger/cdbbridge.py +++ b/share/qtcreator/debugger/cdbbridge.py @@ -76,7 +76,9 @@ class Dumper(DumperBase): self.outputLock = threading.Lock() self.isCdb = True - #FIXME + #FIXME + def register_known_qt_types(self): + DumperBase.register_known_qt_types(self) typeid = self.typeid_for_string('@QVariantMap') del self.type_code_cache[typeid] del self.type_target_cache[typeid] diff --git a/share/qtcreator/debugger/dumper.py b/share/qtcreator/debugger/dumper.py index c2580880f55..58525df2f29 100644 --- a/share/qtcreator/debugger/dumper.py +++ b/share/qtcreator/debugger/dumper.py @@ -172,8 +172,6 @@ class DumperBase(): self.qtCustomEventFunc = 0 self.qtCustomEventPltFunc = 0 self.qtPropertyFunc = 0 - self.qtversion = None - self.qtns = None self.passExceptions = False self.isTesting = False self.qtLoaded = False @@ -189,6 +187,11 @@ class DumperBase(): self.dumpermodules = [] + # These are sticky for the session + self.qtversion = None + self.qtversionAtLeast6 = None + self.qtnamespace = None + self.init_type_cache() try: @@ -211,7 +214,7 @@ class DumperBase(): self.currentPrintsAddress = True self.currentChildType = None self.currentChildNumChild = None - self.register_known_types() + self.register_known_simple_types() def setVariableFetchingOptions(self, args): self.last_args = args @@ -233,9 +236,16 @@ class DumperBase(): self.useTimeStamps = int(args.get('timestamps', '0')) self.partialVariable = args.get('partialvar', '') self.uninitialized = args.get('uninitialized', []) - self.qtversion = args.get('qtversion', 0x060602) - self.qtnamespace = args.get('qtnamespace', '') + self.uninitialized = list(map(lambda x: self.hexdecode(x), self.uninitialized)) + + if self.qtversion is None: + self.qtversion = args.get('qtversion', None) + if self.qtversion == 0: + self.qtversion = None + if self.qtnamespace is None: + self.qtnamespace = args.get('qtnamespace', None) + #self.warn('NAMESPACE: "%s"' % self.qtNamespace()) #self.warn('EXPANDED INAMES: %s' % self.expandedINames) #self.warn('WATCHERS: %s' % self.watchers) @@ -256,11 +266,50 @@ class DumperBase(): args['partialvar'] = '' self.fetchVariables(args) + def extractQtVersion(self): + # can be overridden in bridges + pass + def qtVersion(self): - return self.qtversion + if self.qtversion: + return self.qtversion + + #self.warn("ACCESSING UNKNOWN QT VERSION") + self.qtversion = self.extractQtVersion() + if self.qtversion: + return self.qtversion + + #self.warn("EXTRACTING QT VERSION FAILED. GUESSING NOW.") + if self.qtversionAtLeast6 is None or self.qtversionAtLeast6 is True: + return 0x060602 + return 0x050f00 + + def qtVersionAtLeast(self, version): + # A hack to cover most of the changes from Qt 5 to 6 + if version == 0x60000 and self.qtversionAtLeast6 is not None: + return self.qtversionAtLeast6 + if version == 0x50000: # FIXME: This drops unknown 4.x for now + return True + return self.qtVersion() >= version + + def qtVersionPing(self, typeid, size_for_qt5=-1): + # To be called from places where the type size is sufficient + # to distinguish Qt 5.x and 6.x + if size_for_qt5 == -1: + size_for_qt5 = self.ptrSize() + test_size = self.type_size(typeid) + self.setQtVersionAtLeast6(test_size > size_for_qt5) + + def setQtVersionAtLeast6(self, is6): + if self.qtversionAtLeast6 is None: + #self.warn("SETTING Qt VERSION AT LEAST 6 TO %s" % is6) + self.qtversionAtLeast6 = is6 + self.register_known_qt_types() + #else: + # self.warn("QT VERSION ALREADY KNOWN") def qtNamespace(self): - return self.qtnamespace + return '' if self.qtnamespace is None else self.qtnamespace def resetPerStepCaches(self): self.perStepCache = {} @@ -494,8 +543,13 @@ class DumperBase(): def register_struct(self, name, p5=0, p6=0, s=0, qobject_based=False): # p5 = n -> n * ptrsize for Qt 5 # p6 = n -> n * ptrsize for Qt 6 - #if self.qtVersion() >= 0x060000: # FIXME: Qt 5, ptrSize() - size = 8 * p6 + s + if self.qtversionAtLeast6 is None: + self.warn("TOO EARLY TO GUESS QT VERSION") + size = 8 * p6 + s + elif self.qtversionAtLeast6 is True: + size = 8 * p6 + s + else: + size = 8 * p5 + s typeid = self.typeid_for_string(name) self.type_code_cache[typeid] = TypeCode.Struct self.type_size_cache[typeid] = size @@ -503,7 +557,7 @@ class DumperBase(): self.type_alignment_cache[typeid] = 8 return typeid - def register_known_types(self): + def register_known_simple_types(self): typeid = 0 self.typeid_cache[''] = typeid self.type_code_cache[typeid] = TypeCode.Void @@ -563,6 +617,8 @@ class DumperBase(): self.register_enum('@Qt::ItemDataRole', 4) + def register_known_qt_types(self): + #self.warn("REGISTERING KNOWN QT TYPES NOW") self.register_struct('@QObject', p5=2, p6=2, qobject_based=True) self.register_struct('@QObjectPrivate', p5=10, p6=10) # FIXME: Not exact @@ -711,9 +767,9 @@ class DumperBase(): return limit def vectorData(self, value): - if self.qtVersion() >= 0x060000: + if self.qtVersionAtLeast(0x060000): data, length, alloc = self.qArrayData(value) - elif self.qtVersion() >= 0x050000: + elif self.qtVersionAtLeast(0x050000): vector_data_ptr = self.extractPointer(value) if self.ptrSize() == 4: (ref, length, alloc, offset) = self.split('IIIp', vector_data_ptr) @@ -729,7 +785,7 @@ class DumperBase(): return data, length def qArrayData(self, value): - if self.qtVersion() >= 0x60000: + if self.qtVersionAtLeast(0x60000): dd, data, length = self.split('ppp', value) if dd: _, _, alloc = self.split('iip', dd) @@ -740,7 +796,7 @@ class DumperBase(): def qArrayDataHelper(self, array_data_ptr): # array_data_ptr is what is e.g. stored in a QByteArray's d_ptr. - if self.qtVersion() >= 0x050000: + if self.qtVersionAtLeast(0x050000): # QTypedArray: # - QtPrivate::RefCount ref # - int length @@ -753,7 +809,7 @@ class DumperBase(): data = data & 0xffffffff else: data = data & 0xffffffffffffffff - elif self.qtVersion() >= 0x040000: + elif self.qtVersionAtLeast(0x040000): # Data: # - QBasicAtomicInt ref; # - int alloc, length; @@ -1597,7 +1653,7 @@ class DumperBase(): intSize = 4 ptrSize = self.ptrSize() - if self.qtVersion() >= 0x060000: + if self.qtVersionAtLeast(0x060000): # Size of QObjectData: 9 pointer + 2 int # - vtable # - QObject *q_ptr; @@ -1618,7 +1674,7 @@ class DumperBase(): # - QList > eventFilters; # - QString objectName objectNameAddress = extra + 12 * ptrSize - elif self.qtVersion() >= 0x050000: + elif self.qtVersionAtLeast(0x050000): # Size of QObjectData: 5 pointer + 2 int # - vtable # - QObject *q_ptr; @@ -1811,7 +1867,7 @@ class DumperBase(): # a Q_OBJECT SMO has a non-null superdata (unless it's QObject itself), # a Q_GADGET SMO has a null superdata (hopefully) if result and not isQObjectProper: - if self.qtVersion() >= 0x60000 and self.isWindowsTarget(): + if self.qtVersionAtLeast(0x60000) and self.isWindowsTarget(): (direct, indirect) = self.split('pp', result) # since Qt 6 there is an additional indirect super data getter on windows if direct == 0 and indirect == 0: @@ -1895,14 +1951,14 @@ class DumperBase(): return result def listData(self, value, check=True): - if self.qtVersion() >= 0x60000: + if self.qtVersionAtLeast(0x60000): dd, data, size = self.split('ppi', value) return data, size base = self.extractPointer(value) (ref, alloc, begin, end) = self.split('IIII', base) array = base + 16 - if self.qtVersion() < 0x50000: + if not self.qtVersionAtLeast(0x50000): array += self.ptrSize() size = end - begin @@ -1941,7 +1997,7 @@ class DumperBase(): def metaString(self, metaObjectPtr, index, revision): ptrSize = self.ptrSize() stringdataOffset = ptrSize - if self.isWindowsTarget() and self.qtVersion() >= 0x060000: + if self.isWindowsTarget() and self.qtVersionAtLeast(0x060000): stringdataOffset += ptrSize # indirect super data member stringdata = self.extract_pointer_at_address(int(metaObjectPtr) + stringdataOffset) @@ -1970,19 +2026,19 @@ class DumperBase(): self.putField('sortgroup', sortorder) def putQMetaStuff(self, value, origType): - if self.qtVersion() >= 0x060000: + if self.qtVersionAtLeast(0x060000): metaObjectPtr, handle = value.split('pp') else: metaObjectPtr, handle = value.split('pI') if metaObjectPtr != 0: - if self.qtVersion() >= 0x060000: + if self.qtVersionAtLeast(0x060000): if handle == 0: self.putEmptyValue() return revision = 9 name, alias, flags, keyCount, data = self.split('IIIII', handle) index = name - elif self.qtVersion() >= 0x050000: + elif self.qtVersionAtLeast(0x050000): revision = 7 dataPtr = self.extract_pointer_at_address(metaObjectPtr + 2 * self.ptrSize()) index = self.extractInt(dataPtr + 4 * handle) @@ -2024,7 +2080,7 @@ class DumperBase(): def extractDataPtr(someMetaObjectPtr): # dataPtr = metaObjectPtr['d']['data'] - if self.qtVersion() >= 0x60000 and self.isWindowsTarget(): + if self.qtVersionAtLeast(0x60000) and self.isWindowsTarget(): offset = 3 else: offset = 2 @@ -2054,13 +2110,13 @@ class DumperBase(): extraData = 0 if qobjectPtr: dd = self.extract_pointer_at_address(qobjectPtr + ptrSize) - if self.qtVersion() >= 0x60000: + if self.qtVersionAtLeast(0x60000): (dvtablePtr, qptr, parent, children, bindingStorageData, bindingStatus, flags, postedEvents, dynMetaObjectPtr, # Up to here QObjectData. extraData, threadDataPtr, connectionListsPtr, sendersPtr, currentSenderPtr) \ = self.split('pp{@QObject*}{@QList<@QObject *>}ppIIp' + 'ppppp', dd) - elif self.qtVersion() >= 0x50000: + elif self.qtVersionAtLeast(0x50000): (dvtablePtr, qptr, parent, children, flags, postedEvents, dynMetaObjectPtr, # Up to here QObjectData. extraData, threadDataPtr, connectionListsPtr, @@ -2186,7 +2242,7 @@ typename)) with Children(self): # Static properties. for i in range(propertyCount): - if self.qtVersion() >= 0x60000: + if self.qtVersionAtLeast(0x60000): t = self.split('IIIII', dataPtr + properties * 4 + 20 * i) else: t = self.split('III', dataPtr + properties * 4 + 12 * i) @@ -2239,18 +2295,18 @@ typename)) data += inner_size variant_typeid = self.cheap_typeid_from_name('@QVariant') - if self.qtVersion() >= 0x60000: + if self.qtVersionAtLeast(0x60000): values = vectorGenerator(extraData + 3 * ptrSize, variant_typeid) - elif self.qtVersion() >= 0x50600: + elif self.qtVersionAtLeast(0x50600): values = vectorGenerator(extraData + 2 * ptrSize, variant_typeid) - elif self.qtVersion() >= 0x50000: + elif self.qtVersionAtLeast(0x50000): values = list5Generator(extraData + 2 * ptrSize, variant_typeid) else: variantptr_typeid = self.cheap_typeid_from_name('@QVariant') values = list5Generator(extraData + 2 * ptrSize, variantptr_typeid) bytearray_typeid = self.cheap_typeid_from_name('@QByteArray') - if self.qtVersion() >= 0x60000: + if self.qtVersionAtLeast(0x60000): names = list6Generator(extraData, bytearray_typeid) else: names = list5Generator(extraData + ptrSize, bytearray_typeid) @@ -3427,9 +3483,9 @@ typename)) ): return True if strippedName == 'QStringList': - return self.dumper.qtVersion() >= 0x050000 + return self.dumper.qtVersionAtLeast(0x050000) if strippedName == 'QList': - return self.dumper.qtVersion() >= 0x050600 + return self.dumper.qtVersionAtLeast(0x050600) return False class Field: @@ -3550,7 +3606,7 @@ typename)) if typename.startswith('QList<') or typename.startswith('QVector<'): typeid = self.typeid_for_string(typename) if typeid: - size = 3 * self.ptrSize() if self.qtVersion() >= 0x060000 else self.ptrSize() + size = 3 * self.ptrSize() if self.qtVersionAtLeast(0x060000) else self.ptrSize() self.type_code_cache[typeid] = TypeCode.Struct self.type_size_cache[typeid] = size return typeid diff --git a/share/qtcreator/debugger/gdbbridge.py b/share/qtcreator/debugger/gdbbridge.py index 5e2957b1812..ee25520bced 100644 --- a/share/qtcreator/debugger/gdbbridge.py +++ b/share/qtcreator/debugger/gdbbridge.py @@ -874,6 +874,36 @@ class Dumper(DumperBase): except: return '0x%x' % address + def qtVersionString(self): + try: + return str(gdb.lookup_symbol('qVersion')[0].value()()) + except: + pass + try: + ns = self.qtNamespace() + return str(gdb.parse_and_eval("((const char*(*)())'%sqVersion')()" % ns)) + except: + pass + return None + + def extractQtVersion(self): + try: + # Only available with Qt 5.3+ + return int(str(gdb.parse_and_eval('((void**)&qtHookData)[2]')), 16) + except: + pass + + try: + version = self.qtVersionString() + (major, minor, patch) = version[version.find('"') + 1:version.rfind('"')].split('.') + qtversion = 0x10000 * int(major) + 0x100 * int(minor) + int(patch) + self.qtVersion = lambda: qtversion + return qtversion + except: + # Use fallback until we have a better answer. + return None + + def createSpecialBreakpoints(self, args): self.specialBreakpoints = [] diff --git a/share/qtcreator/debugger/lldbbridge.py b/share/qtcreator/debugger/lldbbridge.py index 7cd3bef77e0..96c149ea025 100644 --- a/share/qtcreator/debugger/lldbbridge.py +++ b/share/qtcreator/debugger/lldbbridge.py @@ -783,6 +783,54 @@ class Dumper(DumperBase): self.fetchInternalFunctions = lambda: None + def extractQtVersion(self): + for func in self.target.FindFunctions('qVersion'): + name = func.GetSymbol().GetName() + if name == None: + continue + if name.endswith('()'): + name = name[:-2] + if name.count(':') > 2: + continue + + #qtNamespace = name[:name.find('qVersion')] + #self.qtNamespace = lambda: qtNamespace + + options = lldb.SBExpressionOptions() + res = self.target.EvaluateExpression(name + '()', options) + + if not res.IsValid() or not res.GetType().IsPointerType(): + exp = '((const char*())%s)()' % name + res = self.target.EvaluateExpression(exp, options) + + if not res.IsValid() or not res.GetType().IsPointerType(): + exp = '((const char*())_Z8qVersionv)()' + res = self.target.EvaluateExpression(exp, options) + + if not res.IsValid() or not res.GetType().IsPointerType(): + continue + + version = str(res) + if version.count('.') != 2: + continue + + version.replace("'", '"') # Both seem possible + version = version[version.find('"') + 1:version.rfind('"')] + + (major, minor, patch) = version.split('.') + qtVersion = 0x10000 * int(major) + 0x100 * int(minor) + int(patch) + return qtVersion + + try: + versionValue = self.target.EvaluateExpression('qtHookData[2]').GetNonSyntheticValue() + if versionValue.IsValid(): + return versionValue.unsigned + except: + pass + + return None + + def handleCommand(self, command): result = lldb.SBCommandReturnObject() self.debugger.GetCommandInterpreter().HandleCommand(command, result) diff --git a/share/qtcreator/debugger/qttypes.py b/share/qtcreator/debugger/qttypes.py index af99534c9b4..a9220636855 100644 --- a/share/qtcreator/debugger/qttypes.py +++ b/share/qtcreator/debugger/qttypes.py @@ -33,7 +33,8 @@ def qedit__QByteArray(d, value, data): def qdump__QByteArray(d, value): - if d.qtVersion() >= 0x60000: + d.qtVersionPing(value.typeid) + if d.qtVersionAtLeast(0x060000): dd, data, length = value.split('ppi') if dd: _, _, alloc = d.split('iii', dd) @@ -76,7 +77,8 @@ def qdump__QByteArray(d, value): def qdump__QBitArray(d, value): - if d.qtVersion() >= 0x60000: + d.qtVersionPing(value.typeid) + if d.qtVersionAtLeast(0x060000): _, data, basize = value.split('ppi') else: data, basize, _ = d.qArrayData(value['d']) @@ -232,13 +234,13 @@ def qdump__QStandardItem(d, value): #d.createType('@QStandardItem*') vtable, dptr = value.split('pp') - if d.qtVersion() >= 0x060000: + if d.qtVersionAtLeast(0x060000): model, parent, values, children, rows, cols, item = \ d.split('pp{@QList<@QStandardItemData>}{@QList<@QStandardItem *>}IIp', dptr) else: # There used to be a virtual destructor that got removed in # 88b6abcebf29b455438 on Apr 18 17:01:22 2017 - if d.qtVersion() < 0x050900 and not d.isMsvcTarget(): + if not d.qtVersionAtLeast(0x050900) and not d.isMsvcTarget(): dptr += d.ptrSize(); model, parent, values, children, rows, cols, item = \ d.split('pp{@QVector<@QStandardItemData>}{@QVector<@QStandardItem *>}IIp', dptr) @@ -266,7 +268,7 @@ def qdump__QDate(d, value): d.enumExpression('DateFormat', 'TextDate')) d.putCallItem('(ISO)', '@QString', value, 'toString', d.enumExpression('DateFormat', 'ISODate')) - if d.qtVersion() < 0x060000: + if not d.qtVersionAtLeast(0x060000): d.putCallItem('(SystemLocale)', '@QString', value, 'toString', d.enumExpression('DateFormat', 'SystemLocaleDate')) d.putCallItem('(Locale)', '@QString', value, 'toString', @@ -286,7 +288,7 @@ def qdump__QTime(d, value): d.enumExpression('DateFormat', 'TextDate')) d.putCallItem('(ISO)', '@QString', value, 'toString', d.enumExpression('DateFormat', 'ISODate')) - if d.canCallLocale() and d.qtVersion() < 0x060000: + if d.canCallLocale() and not d.qtVersionAtLeast(0x060000): d.putCallItem('(SystemLocale)', '@QString', value, 'toString', d.enumExpression('DateFormat', 'SystemLocaleDate')) d.putCallItem('(Locale)', '@QString', value, 'toString', @@ -305,13 +307,12 @@ def qdump__QTimeZone(d, value): def qdump__QDateTime(d, value): - qtVersion = d.qtVersion() isValid = False # This relies on the Qt4/Qt5 internal structure layout: # {sharedref(4), ... base = d.extractPointer(value) is32bit = d.ptrSize() == 4 - if qtVersion >= 0x050200: + if qtVersionAtLeast(0x050200): tiVersion = d.qtTypeInfoVersion() #DumperBase.warn('TI VERSION: %s' % tiVersion) if tiVersion is None: @@ -384,9 +385,9 @@ def qdump__QDateTime(d, value): # - [QTime time;] # - - uint mds; # - Spec spec; - dateSize = 8 if qtVersion >= 0x050000 else 4 # Qt5: qint64, Qt4 uint + dateSize = 8 if qtVersionAtLeast(0x050000) else 4 # Qt5: qint64, Qt4 uint # 4 byte padding after 4 byte QAtomicInt if we are on 64 bit and QDate is 64 bit - refPlusPadding = 8 if qtVersion >= 0x050000 and d.ptrSize() == 8 else 4 + refPlusPadding = 8 if qtVersionAtLeast(0x050000) and d.ptrSize() == 8 else 4 dateBase = base + refPlusPadding timeBase = dateBase + dateSize mds = d.extractInt(timeBase) @@ -410,7 +411,7 @@ def qdump__QDateTime(d, value): d.enumExpression('DateFormat', 'ISODate')) d.putCallItem('toUTC', '@QDateTime', value, 'toTimeSpec', d.enumExpression('TimeSpec', 'UTC')) - if d.qtVersion() < 0x060000: + if not d.qtVersionAtLeast(0x060000): d.putCallItem('(SystemLocale)', '@QString', value, 'toString', d.enumExpression('DateFormat', 'SystemLocaleDate')) d.putCallItem('(Locale)', '@QString', value, 'toString', @@ -756,7 +757,6 @@ def qdump__QFile(d, value): def qdump__QFileInfo(d, value): privAddress = d.extractPointer(value) #bit32 = d.ptrSize() == 4 - #qt5 = d.qtVersion() >= 0x050000 #try: # d.putStringValue(value['d_ptr']['d'].dereference()['fileNames'][3]) #except: @@ -876,7 +876,7 @@ def qdump__QVariantHash(d, value): def qdumpHelper_QHash(d, value, keyType, valueType): - if d.qtVersion() >= 0x60000: + if d.qtVersionAtLeast(0x060000): qdumpHelper_QHash_6(d, value, keyType, valueType) else: qdumpHelper_QHash_5(d, value, keyType, valueType) @@ -918,7 +918,7 @@ def qdumpHelper_QHash_5(d, value, keyType, valueType): d.putItemCount(size) if d.isExpanded(): - isShort = d.qtVersion() < 0x050000 and keyType.name == 'int' + isShort = not d.qtVersionAtLeast(0x050000) and keyType.name == 'int' with Children(d, size): node = hashDataFirstNode() for i in d.childRange(): @@ -994,7 +994,7 @@ def qHashIteratorHelper(d, value): if d.isExpanded(): with Children(d): node = d.extractPointer(value) - isShort = d.qtVersion() < 0x050000 and keyType.name == 'int' + isShort = not d.qtVersionAtLeast(0x050000) and keyType.name == 'int' if isShort: typeCode = 'P{%s}@{%s}' % (keyType.name, valueType.name) (pnext, key, padding2, val) = d.split(typeCode, node) @@ -1015,9 +1015,8 @@ def qdump__QHash__iterator(d, value): def qdump__QHostAddress(d, value): dd = d.extractPointer(value) - qtVersion = d.qtVersion() tiVersion = d.qtTypeInfoVersion() - #DumperBase.warn('QT: %x, TI: %s' % (qtVersion, tiVersion)) + #DumperBase.warn('QT: %x, TI: %s' % (d.qtVersion(), tiVersion)) mayNeedParse = True if tiVersion is not None: if tiVersion >= 16: @@ -1032,14 +1031,14 @@ def qdump__QHostAddress(d, value): else: (ipString, scopeId, a4, pad, a6, protocol, isParsed) \ = d.split('{@QString}{@QString}{@quint32}I16sI{bool}', dd) - elif qtVersion >= 0x050600: # 5.6.0 at f3aabb42 + elif qtVersionAtLeast(0x050600): # 5.6.0 at f3aabb42 if d.ptrSize() == 8 or d.isWindowsTarget(): (ipString, scopeId, a4, pad, a6, protocol, isParsed) \ = d.split('{@QString}{@QString}{@quint32}I16sI{bool}', dd) else: (ipString, scopeId, a4, a6, protocol, isParsed) \ = d.split('{@QString}{@QString}{@quint32}16sI{bool}', dd) - elif qtVersion >= 0x050000: # 5.2.0 at 62feb088 + elif qtVersionAtLeast(0x050000): # 5.2.0 at 62feb088 (ipString, scopeId, a4, a6, protocol, isParsed) \ = d.split('{@QString}{@QString}{@quint32}16sI{bool}', dd) else: # 4.8.7 at b05d05f @@ -1104,7 +1103,8 @@ def qdumpHelper_QList(d, value, inner_typish): data, size = d.listData(value, check=True) d.putItemCount(size) - if d.qtVersion() >= 0x60000: + d.qtVersionPing(value.typeid) + if d.qtVersionAtLeast(0x060000): d.putPlotData(data, size, innerType) return @@ -1145,9 +1145,9 @@ def qform__QImage(): def qdump__QImage(d, value): - if d.qtVersion() >= 0x060000: + if d.qtVersionAtLeast(0x060000): vtbl, painters, image_data = value.split('ppp') - elif d.qtVersion() >= 0x050000: + elif d.qtVersionAtLeast(0x050000): vtbl, painters, reserved, image_data = value.split('pppp') else: vtbl, painters, image_data = value.split('ppp') @@ -1161,12 +1161,12 @@ def qdump__QImage(d, value): d.putExpandable() if d.isExpanded(): - if d.qtVersion() < 0x060000: - (ref, width, height, depth, nbytes, pad, devicePixelRatio, colorTable, - bits, iformat) = d.split('iiiii@dppi', image_data) - else: + if d.qtVersionAtLeast(0x060000): (ref, width, height, depth, nbytes, pad, devicePixelRatio, _, _, _, bits, iformat) = d.split('iiiii@dppppi', image_data) + else: + (ref, width, height, depth, nbytes, pad, devicePixelRatio, colorTable, + bits, iformat) = d.split('iiiii@dppi', image_data) with Children(d): d.putIntItem('width', width) d.putIntItem('height', height) @@ -1222,8 +1222,7 @@ def qdump__QLocale(d, value): # index = int(value['d']['d']['m_data']...) #d.check(index >= 0) #d.check(index <= qqLocalesCount) - qtVersion = d.qtVersion() - if qtVersion < 0x50000: + if not d.qtVersionAtLeast(0x50000): d.putStringValue(d.call('const char *', value, 'name')) d.putPlainChildren(value) return @@ -1240,7 +1239,7 @@ def qdump__QLocale(d, value): prefix = ns + 'QLocale::' try: - if qtVersion >= 0x060700: + if qtVersionAtLeast(0x060700): res = d.call('const char *', value, 'name', prefix + 'TagSeparator::Underscore') else: res = d.call('const char *', value, 'name') @@ -1347,9 +1346,9 @@ def qdump__QMap(d, value): def qdumpHelper_QMap(d, value, keyType, valueType): - if d.qtVersion() >= 0x60000: + if d.qtVersionAtLeast(0x060000): qdumpHelper_Qt6_QMap(d, value, keyType, valueType) - elif d.qtVersion() >= 0x50000: + elif d.qtVersionAtLeast(0x50000): qdumpHelper_Qt5_QMap(d, value, keyType, valueType) else: qdumpHelper_Qt4_QMap(d, value, keyType, valueType) @@ -1369,7 +1368,7 @@ def qdumpHelper_Qt6_QMultiMap(d, value, keyType, valueType): d.putBetterType('@QMultiMap<%s, %s>' % (keyType.name, valueType.name)) def qdump__QMultiMap(d, value): - if d.qtVersion() >= 0x60000: + if d.qtVersionAtLeast(0x060000): qdumpHelper_Qt6_QMultiMap(d, value, value.type[0], value.type[1]) else: qdump__QMap(d, value) @@ -1449,9 +1448,9 @@ def qdump__QProcEnvKey(d, value): def qdump__QPixmap(d, value): - if d.qtVersion() >= 0x060000: + if d.qtVersionAtLeast(0x060000): vtbl, painters, data = value.split('ppp') - elif d.qtVersion() >= 0x050000: + elif d.qtVersionAtLeast(0x050000): vtbl, painters, reserved, data = s = d.split('pppp', value) else: vtbl, painters, data = value.split('ppp') @@ -1518,15 +1517,15 @@ def qdump__QRegion(d, value): if d_ptr == 0: d.putSpecialValue('empty') else: - if d.qtVersion() >= 0x060000: + if d.qtVersionAtLeast(0x060000): ref, _, rgn = d.split('i@p', d_ptr) numRects, innerArea, rects, extents, innerRect = \ d.split('ii{@QList<@QRect>}{@QRect}{@QRect}', rgn) - elif d.qtVersion() >= 0x050400: # Padding removed in ee324e4ed + elif d.qtVersionAtLeast(0x050400): # Padding removed in ee324e4ed ref, _, rgn = d.split('i@p', d_ptr) numRects, innerArea, rects, extents, innerRect = \ d.split('ii{@QVector<@QRect>}{@QRect}{@QRect}', rgn) - elif d.qtVersion() >= 0x050000: + elif d.qtVersionAtLeast(0x050000): ref, _, rgn = d.split('i@p', d_ptr) numRects, _, rects, extents, innerRect, innerArea = \ d.split('i@{@QVector<@QRect>}{@QRect}{@QRect}i', rgn) @@ -1564,7 +1563,7 @@ def qdump__QScopedPointer(d, value): def qdump__QSet(d, value): - if d.qtVersion() >= 0x060000: + if d.qtVersionAtLeast(0x060000): qdumpHelper_QSet6(d, value) else: qdumpHelper_QSet45(d, value) @@ -1637,7 +1636,7 @@ def qdumpHelper_QSet45(d, value): d.putItemCount(length) if d.isExpanded(): keyType = value.type[0] - isShort = d.qtVersion() < 0x050000 and keyType.name == 'int' + isShort = not d.qtVersionAtLeast(0x050000) and keyType.name == 'int' with Children(d, length, childType=keyType): node = hashDataFirstNode() for i in d.childRange(): @@ -1714,7 +1713,7 @@ def qform__QStack(): def qdump__QStack(d, value): - if d.qtVersion() >= 0x60000: + if d.qtVersionVersionAtLeast(0x060000): qdump__QList(d, value) else: qdump__QVector(d, value) @@ -1734,7 +1733,7 @@ def qdump__QPolygon(d, value): def qdump__QGraphicsPolygonItem(d, value): (vtbl, dptr) = value.split('pp') - if d.qtVersion() >= 0x060000: + if d.qtVersionAtLeast(0x060000): if d.ptrSize() == 8: offset = 424 # sizeof(QGraphicsPolygonItemPrivate), the base else: @@ -1764,6 +1763,7 @@ def qform__QString(): def qdump__QString(d, value): + d.qtVersionPing(value.typeid) d.putStringValue(value) data, length, _ = d.stringData(value) displayFormat = d.currentItemFormat() @@ -1924,7 +1924,7 @@ def qdump__QUrl(d, value): d.putValue('') return - if d.qtVersion() < 0x050000: + if not d.qtVersionAtLeast(0x050000): d.call('void', value, 'port') # Warm up internal cache. d.call('void', value, 'path') st = '{@QString}' @@ -2154,7 +2154,8 @@ qdumpHelper_QVariants_F = [ def qdump__QVariant(d, value): - if d.qtVersion() >= 0x060000: + d.qtVersionPing(value.typeid, 2 * d.ptrSize()) + if d.qtVersionAtLeast(0x060000): qdumpHelper__QVariant6(d, value) else: qdumpHelper__QVariant45(d, value) @@ -2208,12 +2209,12 @@ def qdumpHelper__QVariant45(d, value): return None # Extended Core type (Qt 5) - if variantType >= 31 and variantType <= 38 and d.qtVersion() >= 0x050000: + if variantType >= 31 and variantType <= 38 and d.qtVersionAtLeast(0x050000): qdumpHelper_QVariants_D[variantType - 31](d, value) return None # Extended Core type (Qt 4) - if variantType >= 128 and variantType <= 135 and d.qtVersion() < 0x050000: + if variantType >= 128 and variantType <= 135 and not d.qtVersionAtLeast(0x050000): if variantType == 128: d.putBetterType('@QVariant (void *)') d.putValue('0x%x' % value.extractPointer()) @@ -2234,7 +2235,7 @@ def qdumpHelper__QVariant45(d, value): innert = qdumpHelper_QVariants_B[variantType - 7] elif variantType <= 74: innert = qdumpHelper_QVariants_E[variantType - 64] - elif d.qtVersion() < 0x050000: + elif not d.qtVersionAtLeast(0x050000): innert = qdumpHelper_QVariants_F[variantType - 76] else: innert = qdumpHelper_QVariants_F[variantType - 75] @@ -2308,7 +2309,8 @@ def qform__QVector(): def qdump__QVector(d, value): - if d.qtVersion() >= 0x060000: + d.qtVersionPing(value.typeid) + if d.qtVersionAtLeast(0x060000): data, length = d.listData(value) d.putItemCount(length) d.putPlotData(data, length, value.type.target()[0]) @@ -2330,7 +2332,7 @@ if False: def qdump__QVarLengthArray(d, value): - if d.qtVersion() >= 0x060000: + if d.qtVersionAtLeast(0x060000): cap, length, data = value.split('QQp') else: cap, length, data = value.split('iip') @@ -2366,7 +2368,7 @@ def qdump_QWeakPointerHelper(d, value, isWeak, innerType=None): d.putValue('') return - if d.qtVersion() >= 0x050000: + if d.qtVersionAtLeast(0x050000): (weakref, strongref) = d.split('ii', d_ptr) else: (vptr, weakref, strongref) = d.split('pii', d_ptr) @@ -2872,7 +2874,7 @@ def qdump__QJSValue(d, value): if d.ptrSize() == 4: qdump_32__QJSValue(d, value) else: - if d.qtVersion() >= 0x60000: + if d.qtVersionAtLeast(0x060000): qdump_64__QJSValue_6(d, value) else: qdump_64__QJSValue_5(d, value) @@ -2906,7 +2908,7 @@ def qdump_64__QJSValue_6(d, value): if dd == 0: d.putValue('(undefined)') d.putType(value.type.name + ' (undefined)') - if d.qtVersion() < 0x60500: + if not d.qtVersionAtLeast(0x60500): typ = dd >> 47 if typ == 5: d.putValue('(null)') @@ -3326,7 +3328,7 @@ def qdumpHelper_QJsonObject(d, data, obj): def qdump__QJsonValue(d, value): (data, dd, t) = value.split('QpI') - if d.qtVersion() >= 0x050f00: + if d.qtVersionAtLeast(0x050f00): value = d.createProxyValue((data, dd, t, False), 'QCborValue_proxy') d.putItem(value) return @@ -3361,13 +3363,13 @@ def qdump__QJsonValue(d, value): def qdump__QJsonArray(d, value): - if d.qtVersion() >= 0x060000: + if d.qtVersionAtLeast(0x060000): dptr = d.extractPointer(value) if not dptr: d.putItemCount(0) else: qdumpHelper_QCbor_array(d, dptr, False) - elif d.qtVersion() >= 0x050f00: + elif d.qtVersionAtLeast(0x050f00): _, container_ptr = value.split('pp') qdumpHelper_QCbor_array(d, container_ptr, False) else: @@ -3375,13 +3377,13 @@ def qdump__QJsonArray(d, value): def qdump__QJsonObject(d, value): - if d.qtVersion() >= 0x060000: + if d.qtVersionAtLeast(0x060000): dptr = d.extractPointer(value) if not dptr: d.putItemCount(0) else: qdumpHelper_QCbor_map(d, dptr, False) - elif d.qtVersion() >= 0x050f00: + elif d.qtVersionAtLeast(0x050f00): _, container_ptr = value.split('pp') qdumpHelper_QCbor_map(d, container_ptr, False) else: @@ -3456,15 +3458,15 @@ def qdump__qfloat16(d, value): def qdumpHelper_QCbor_string(d, container_ptr, element_index, is_bytes): # d.split('i@{@QByteArray::size_type}pp', container_ptr) doesn't work with CDB, # so be explicit: - data_pos = container_ptr + (2 * d.ptrSize() if d.qtVersion() >= 0x060000 else 8) - elements_pos = data_pos + (3 * d.ptrSize() if d.qtVersion() >= 0x060000 else d.ptrSize()) + data_pos = container_ptr + (2 * d.ptrSize() if d.qtVersionAtLeast(0x060000) else 8) + elements_pos = data_pos + (3 * d.ptrSize() if d.qtVersionAtLeast(0x060000) else d.ptrSize()) elements_data_ptr, elements_size = d.vectorData(elements_pos) element_at_n_addr = elements_data_ptr + element_index * 16 # sizeof(QtCbor::Element) == 16 element_value, _, element_flags = d.split('qII', element_at_n_addr) enc = 'latin1' if is_bytes or (element_flags & 8) else 'utf16' bytedata, _, _ = d.qArrayData(data_pos) bytedata += element_value - if d.qtVersion() >= 0x060000: + if d.qtVersionAtLeast(0x060000): bytedata_len = d.extractInt64(bytedata) bytedata_data = bytedata + 8 else: @@ -3493,8 +3495,8 @@ def qdumpHelper_QCbor_array(d, container_ptr, is_cbor): return # d.split('i@{@QByteArray::size_type}pp', container_ptr) doesn't work with CDB, # so be explicit: - data_pos = container_ptr + (2 * d.ptrSize() if d.qtVersion() >= 0x060000 else 8) - elements_pos = data_pos + (3 * d.ptrSize() if d.qtVersion() >= 0x060000 else d.ptrSize()) + data_pos = container_ptr + (2 * d.ptrSize() if d.qtVersionAtLeast(0x060000) else 8) + elements_pos = data_pos + (3 * d.ptrSize() if d.qtVersionAtLeast(0x060000) else d.ptrSize()) elements_data_ptr, elements_size = d.vectorData(elements_pos) d.putItemCount(elements_size) if d.isExpanded(): @@ -3515,8 +3517,8 @@ def qdumpHelper_QCbor_map(d, container_ptr, is_cbor): return # d.split('i@{@QByteArray::size_type}pp', container_ptr) doesn't work with CDB, # so be explicit: - data_pos = container_ptr + (2 * d.ptrSize() if d.qtVersion() >= 0x060000 else 8) - elements_pos = data_pos + (3 * d.ptrSize() if d.qtVersion() >= 0x060000 else d.ptrSize()) + data_pos = container_ptr + (2 * d.ptrSize() if d.qtVersionAtLeast(0x060000) else 8) + elements_pos = data_pos + (3 * d.ptrSize() if d.qtVersionAtLeast(0x060000) else d.ptrSize()) elements_data_ptr, elements_size = d.vectorData(elements_pos) elements_size = int(elements_size / 2) d.putItemCount(elements_size) From cf64d46bbebe636649cfd12c768aae31ef707bdb Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Mon, 27 May 2024 11:44:17 +0200 Subject: [PATCH 09/24] Markdown: Implement navigation history The text editor widget now tells us when it thinks a new navigation point should be added, so do it. Change-Id: I20e65134420cb1d94d7bc5310791d07ff951647c Reviewed-by: David Schulz --- src/plugins/texteditor/markdowneditor.cpp | 28 +++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/plugins/texteditor/markdowneditor.cpp b/src/plugins/texteditor/markdowneditor.cpp index c08fedeb104..93b580a935e 100644 --- a/src/plugins/texteditor/markdowneditor.cpp +++ b/src/plugins/texteditor/markdowneditor.cpp @@ -110,6 +110,21 @@ public: m_textEditorWidget->setTextDocument(m_document); m_textEditorWidget->setupGenericHighlighter(); m_textEditorWidget->setMarksVisible(false); + QObject::connect( + m_textEditorWidget, + &TextEditorWidget::saveCurrentStateForNavigationHistory, + this, + &MarkdownEditor::saveCurrentStateForNavigationHistory); + QObject::connect( + m_textEditorWidget, + &TextEditorWidget::addSavedStateToNavigationHistory, + this, + &MarkdownEditor::addSavedStateToNavigationHistory); + QObject::connect( + m_textEditorWidget, + &TextEditorWidget::addCurrentStateToNavigationHistory, + this, + &MarkdownEditor::addCurrentStateToNavigationHistory); auto context = new IContext(this); context->setWidget(m_textEditorWidget); context->setContext(Context(MARKDOWNVIEWER_TEXT_CONTEXT)); @@ -476,6 +491,18 @@ private: } } + void saveCurrentStateForNavigationHistory() { m_savedNavigationState = saveState(); } + + void addSavedStateToNavigationHistory() + { + EditorManager::addCurrentPositionToNavigationHistory(m_savedNavigationState); + } + + void addCurrentStateToNavigationHistory() + { + EditorManager::addCurrentPositionToNavigationHistory(); + } + private: QTimer m_previewTimer; bool m_performDelayedUpdate = false; @@ -491,6 +518,7 @@ private: QAction *m_togglePreviewVisibleAction; QAction *m_swapViewsAction; std::optional m_previewRestoreScrollPosition; + QByteArray m_savedNavigationState; }; class MarkdownEditorFactory final : public IEditorFactory From 6c98cb780d970c1c80e3264be5f4757f8757d4a9 Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Fri, 31 May 2024 15:57:51 +0200 Subject: [PATCH 10/24] Doc: Describe configuring C++ code model for a project Task-number: QTCREATORBUG-30604 Change-Id: I8f3634fe4282ebe3d364f7762fe651ddb872313f Reviewed-by: Christian Kandeler --- .../qtcreator-projects-cpp-code-model.webp | Bin 0 -> 3290 bytes .../creator-only/creator-clang-codemodel.qdoc | 88 ++++++++++++------ .../creator-projects-settings-overview.qdoc | 1 + 3 files changed, 60 insertions(+), 29 deletions(-) create mode 100644 doc/qtcreator/images/qtcreator-projects-cpp-code-model.webp diff --git a/doc/qtcreator/images/qtcreator-projects-cpp-code-model.webp b/doc/qtcreator/images/qtcreator-projects-cpp-code-model.webp new file mode 100644 index 0000000000000000000000000000000000000000..259d8092f30ef55d70b2af7f8e13d01a61ed532a GIT binary patch literal 3290 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 BP&WVo literal 0 HcmV?d00001 diff --git a/doc/qtcreator/src/editors/creator-only/creator-clang-codemodel.qdoc b/doc/qtcreator/src/editors/creator-only/creator-clang-codemodel.qdoc index bdf06e24eb4..d8bba6edf62 100644 --- a/doc/qtcreator/src/editors/creator-only/creator-clang-codemodel.qdoc +++ b/doc/qtcreator/src/editors/creator-only/creator-clang-codemodel.qdoc @@ -124,8 +124,34 @@ The document outline in the \l{Outline} view is backed by clangd's document symbol support, which makes the results more reliable than before. - \sa {Code Model}, {Clangd}, {Specify clangd settings}, - {Specify Clang tools settings}, {Use compilation databases} + \sa {Configure C++ code model}, {Specify clangd settings}, + {Specify Clang tools settings}, {Use compilation databases}, + {Code Model}, {Clangd} +*/ + +/*! + \page creator-how-to-cpp-code-model.html + \previouspage creator-how-tos.html + + \ingroup creator-how-to-configure-editors + \ingroup creator-how-to-projects-configure + + \title Configure C++ code model + + The code model offers services such as code completion, syntactic and + semantic highlighting, and diagnostics. + + To configure the C++ code model for a project: + + \list 1 + \li Go to \uicontrol Projects > \uicontrol {Project Settings} > + \uicontrol {C++ Code Model}. + \image qtcreator-projects-cpp-code-model.webp {C++ Code Model settings} + \li Clear \uicontrol {Use global settings}. + \li Set \uicontrol {C++ Code Model} settings for the project. + \endlist + + \sa {Code Model} */ /*! @@ -138,40 +164,43 @@ \brief Sets global preferences for the code model. - The Clang code model offers services such as code completion, syntactic and + The code model offers services such as code completion, syntactic and semantic highlighting, and diagnostics. - To configure the Clang code model globally: + To configure the C++ code model globally, go to \preferences > + \uicontrol C++ > \uicontrol {Code Model}. - \list 1 + \image qtcreator-preferences-code-model.webp {C++ Code Model preferences} - \li Select \preferences > \uicontrol C++ > - \uicontrol {Code Model}. - - \image qtcreator-preferences-code-model.webp {C++ Code Model preferences} - - \li To instruct the code model to interpret ambiguous header files as C - language files if you develop mainly using C, select the - \uicontrol {Interpret ambiguous headers as C headers} check box. - - \li To process precompiled headers, deselect the - \uicontrol {Ignore precompiled headers} check box. - - \li To use the built-in preprocessor to show the - pre-processed source file in the editor, select - \uicontrol {Use built-in preprocessor to show pre-processed files}. + The following table summarizes the preferences. + \table + \header + \li Setting + \li Value + \row + \li \uicontrol {Interpret ambiguous headers as C headers} + \li Instructs the code model to interpret ambiguous header files as C + language files. Select this checkbox if you develop mainly using C. + \row + \li \uicontrol {Ignore precompiled headers} + \li Clear this checkbox to process precompiled headers. + \row + \li \uicontrol {Use built-in preprocessor to show pre-processed files} + \li Uses the built-in preprocessor to show the + pre-processed source file in the editor. + \row + \li \uicontrol {Do not index files greater than} \li To avoid out-of-memory crashes caused by indexing huge source files that are typically auto-generated by scripts or code, the size of - files to index is limited to 5MB by default. To adjust the limit, - edit the value for the \uicontrol {Do not index files greater than} - check box. To index all files, deselect the check box. + files to index is limited to 5MB by default. - \li To ignore files that match wildcard patterns, select the - \uicontrol {Ignore files} check box and enter each wildcard pattern - on a separate line in the field. - - \endlist + To index all files, clear the checkbox. + \row + \li \uicontrol {Ignore files} + \li To ignore files that match wildcard patterns, enter each wildcard + pattern on a separate line in the field. + \endtable \section1 Inspect preprocessed C++ code @@ -186,7 +215,8 @@ this action also expands all \c {"#include "} statements to their actual contents. - \sa {Specify clangd settings}, {Clang Code Model}, {Clangd} + \sa {Configure C++ code model}, {Specify clangd settings}, + {Clang Code Model}, {Clangd} */ /*! diff --git a/doc/qtcreator/src/projects/creator-only/creator-projects-settings-overview.qdoc b/doc/qtcreator/src/projects/creator-only/creator-projects-settings-overview.qdoc index df0b2b0f7a7..3f8e93f1421 100644 --- a/doc/qtcreator/src/projects/creator-only/creator-projects-settings-overview.qdoc +++ b/doc/qtcreator/src/projects/creator-only/creator-projects-settings-overview.qdoc @@ -85,6 +85,7 @@ \li \l{Specify clangd settings}{Clangd} \li \l{Specify Clang tools settings}{Clang Tools} \li \l{Set Copilot preferences}{Copilot} + \li \l{Configure C++ code model}{C++ Code Model} \li \l{Specify code style}{C++ Code Style} \li \l{Set C++ file naming preferences}{C++ File Naming} \li \l{Specify dependencies}{Dependencies} From 0f983f2e95e8f9208819b3b943ce74ece3903b67 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Tue, 11 Jun 2024 14:55:43 +0200 Subject: [PATCH 11/24] Axivion: Remove unused lambda capture Amends dbe2e422f7fb17b6f25bc2a8c7dcd8c5127fb672. Change-Id: I06e75ff43a9504f4b1c06670427c1ec95bddafe9 Reviewed-by: Jarek Kobus --- src/plugins/axivion/axivionoutputpane.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/axivion/axivionoutputpane.cpp b/src/plugins/axivion/axivionoutputpane.cpp index d3043a12751..644db7f5433 100644 --- a/src/plugins/axivion/axivionoutputpane.cpp +++ b/src/plugins/axivion/axivionoutputpane.cpp @@ -149,7 +149,7 @@ void DashboardWidget::updateUi() } return prefix; }; - auto linked = [this](const QString &text, const QString &href, bool link) { + auto linked = [](const QString &text, const QString &href, bool link) { return link ? QString("%2").arg(href).arg(text) : text; }; From 9d88da6c2bc40b17215137d9b2face5aafdfae3d Mon Sep 17 00:00:00 2001 From: David Schulz Date: Mon, 10 Jun 2024 15:18:15 +0200 Subject: [PATCH 12/24] Debugger: simplify interrupting windows processes The win32interrupt.exe is gone. And since we do not support 32bit Qt Creator builds anymore there is no purpose for a win64interrupt.exe. Since some 'recent' changes interrupting the cdb works now by simply setting Process::setUseCtrlCStub and calling Process::interrupt on the debugger process. The same seems to work with gdb nowadays, but we need to expect the SIGINT signal that gdb receives in this situation. Otherwise the user will be shown a message box about the emission of that signal. Change-Id: I7a21d7ea34409d8bbf62d94e28387d591e7feb3d Reviewed-by: Christian Stenger --- src/plugins/debugger/gdb/gdbengine.cpp | 39 ++---- src/plugins/debugger/pdb/pdbengine.cpp | 2 +- src/plugins/debugger/procinterrupt.cpp | 132 ++---------------- src/plugins/debugger/procinterrupt.h | 3 +- .../desktopprocesssignaloperation.cpp | 96 ++----------- 5 files changed, 36 insertions(+), 236 deletions(-) diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index 1079fb24eaf..ab173cc0eab 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -124,6 +124,7 @@ const char notCompatibleMessage[] = "is not compatible with target architecture" GdbEngine::GdbEngine() { m_gdbProc.setProcessMode(ProcessMode::Writer); + m_gdbProc.setUseCtrlCStub(true); setObjectName("GdbEngine"); setDebuggerName("GDB"); @@ -673,26 +674,7 @@ void GdbEngine::interruptInferior() } else { showStatusMessage(Tr::tr("Stop requested..."), 5000); showMessage("TRYING TO INTERRUPT INFERIOR"); - if (HostOsInfo::isWindowsHost() && !m_isQnxGdb) { - IDevice::ConstPtr dev = device(); - QTC_ASSERT(dev, notifyInferiorStopFailed(); return); - DeviceProcessSignalOperation::Ptr signalOperation = dev->signalOperation(); - QTC_ASSERT(signalOperation, notifyInferiorStopFailed(); return); - connect(signalOperation.get(), &DeviceProcessSignalOperation::finished, - this, [this, signalOperation](const QString &error) { - if (error.isEmpty()) { - showMessage("Interrupted " + QString::number(inferiorPid())); - notifyInferiorStopOk(); - } else { - showMessage(error, LogError); - notifyInferiorStopFailed(); - } - }); - signalOperation->setDebuggerCommand(runParameters().debugger.command.executable()); - signalOperation->interruptProcess(inferiorPid()); - } else { - interruptInferior2(); - } + interruptInferior2(); } } @@ -1265,9 +1247,11 @@ void GdbEngine::handleStopResponse(const GdbMi &data) handleStop1(data); } -static QString stopSignal(const Abi &abi) +static QStringList stopSignals(const Abi &abi) { - return QLatin1String(abi.os() == Abi::WindowsOS ? "SIGTRAP" : "SIGINT"); + static QStringList winSignals = { "SIGTRAP", "SIGINT" }; + static QStringList unixSignals = { "SIGINT" }; + return abi.os() == Abi::WindowsOS ? winSignals : unixSignals; } void GdbEngine::handleStop1(const GdbMi &data) @@ -1416,7 +1400,7 @@ void GdbEngine::handleStop2(const GdbMi &data) QString meaning = data["signal-meaning"].data(); // Ignore these as they are showing up regularly when // stopping debugging. - if (name == stopSignal(rp.toolChainAbi) || rp.expectedSignals.contains(name)) { + if (stopSignals(rp.toolChainAbi).contains(name) || rp.expectedSignals.contains(name)) { showMessage(name + " CONSIDERED HARMLESS. CONTINUING."); } else if (m_isQnxGdb && name == "0" && meaning == "Signal 0") { showMessage("SIGNAL 0 CONSIDERED BOGUS."); @@ -3817,9 +3801,6 @@ void GdbEngine::setupEngine() CHECK_STATE(EngineSetupRequested); showMessage("TRYING TO START ADAPTER"); - if (isRemoteEngine()) - m_gdbProc.setUseCtrlCStub(runParameters().useCtrlCStub); // This is only set for QNX - const DebuggerRunParameters &rp = runParameters(); CommandLine gdbCommand = rp.debugger.command; @@ -4314,7 +4295,6 @@ void GdbEngine::interruptLocalInferior(qint64 pid) showMessage("TRYING TO INTERRUPT INFERIOR BEFORE PID WAS OBTAINED", LogError); return; } - QString errorMessage; if (runParameters().runAsRoot) { Environment env = Environment::systemEnvironment(); RunControl::provideAskPassEntry(env); @@ -4323,11 +4303,8 @@ void GdbEngine::interruptLocalInferior(qint64 pid) proc.setEnvironment(env); proc.start(); proc.waitForFinished(); - } else if (interruptProcess(pid, GdbEngineType, &errorMessage)) { - showMessage("Interrupted " + QString::number(pid)); } else { - showMessage(errorMessage, LogError); - notifyInferiorStopFailed(); + m_gdbProc.interrupt(); } } diff --git a/src/plugins/debugger/pdb/pdbengine.cpp b/src/plugins/debugger/pdb/pdbengine.cpp index e0bfa126f5a..657447f17e0 100644 --- a/src/plugins/debugger/pdb/pdbengine.cpp +++ b/src/plugins/debugger/pdb/pdbengine.cpp @@ -143,7 +143,7 @@ void PdbEngine::handlePdbStarted() void PdbEngine::interruptInferior() { QString error; - interruptProcess(m_proc.processId(), GdbEngineType, &error); + interruptProcess(m_proc.processId(), &error); } void PdbEngine::executeStepIn(bool) diff --git a/src/plugins/debugger/procinterrupt.cpp b/src/plugins/debugger/procinterrupt.cpp index 113fbeefc4f..0f104f3bfc0 100644 --- a/src/plugins/debugger/procinterrupt.cpp +++ b/src/plugins/debugger/procinterrupt.cpp @@ -23,128 +23,23 @@ static inline QString msgCannotInterrupt(qint64 pid, const QString &why) # define PROCESS_SUSPEND_RESUME (0x0800) #endif // PROCESS_SUSPEND_RESUME -static BOOL isWow64Process(HANDLE hproc) -{ - using LPFN_ISWOW64PROCESS = BOOL (WINAPI*)(HANDLE, PBOOL); - - BOOL ret = false; - - static LPFN_ISWOW64PROCESS fnIsWow64Process = NULL; - if (!fnIsWow64Process) { - if (HMODULE hModule = GetModuleHandle(L"kernel32.dll")) - fnIsWow64Process = reinterpret_cast(GetProcAddress(hModule, "IsWow64Process")); - } - - if (!fnIsWow64Process) { - qWarning("Cannot retrieve symbol 'IsWow64Process'."); - return false; - } - - if (!fnIsWow64Process(hproc, &ret)) { - qWarning("IsWow64Process() failed for %p: %s", - hproc, qPrintable(Utils::winErrorMessage(GetLastError()))); - return false; - } - return ret; -} - // Open the process and break into it -bool Debugger::Internal::interruptProcess(qint64 pID, int engineType, QString *errorMessage, const bool engineExecutableIs64Bit) +bool Debugger::Internal::interruptProcess(qint64 pID, QString *errorMessage) { bool ok = false; HANDLE inferior = NULL; - do { - const DWORD rights = PROCESS_QUERY_INFORMATION|PROCESS_SET_INFORMATION - |PROCESS_VM_OPERATION|PROCESS_VM_WRITE|PROCESS_VM_READ - |PROCESS_DUP_HANDLE|PROCESS_TERMINATE|PROCESS_CREATE_THREAD|PROCESS_SUSPEND_RESUME; - inferior = OpenProcess(rights, FALSE, DWORD(pID)); - if (inferior == NULL) { - *errorMessage = QString::fromLatin1("Cannot open process %1: %2"). - arg(pID).arg(Utils::winErrorMessage(GetLastError())); - break; - } + const DWORD rights = PROCESS_QUERY_INFORMATION | PROCESS_SET_INFORMATION | PROCESS_VM_OPERATION + | PROCESS_VM_WRITE | PROCESS_VM_READ | PROCESS_DUP_HANDLE + | PROCESS_TERMINATE | PROCESS_CREATE_THREAD | PROCESS_SUSPEND_RESUME; + inferior = OpenProcess(rights, FALSE, DWORD(pID)); + if (inferior == NULL) { + *errorMessage = QString::fromLatin1("Cannot open process %1: %2") + .arg(pID) + .arg(Utils::winErrorMessage(GetLastError())); + } else if (ok = DebugBreakProcess(inferior); !ok) { + *errorMessage = "DebugBreakProcess failed: " + Utils::winErrorMessage(GetLastError()); + } - enum DebugBreakApi { - UseDebugBreakApi, - UseWin64Interrupt, - UseWin32Interrupt - }; -/* - Windows 64 bit has a 32 bit subsystem (WOW64) which makes it possible to run a - 32 bit application inside a 64 bit environment. - When GDB is used DebugBreakProcess must be called from the same system (32/64 bit) running - the inferior. If CDB is used we could in theory break wow64 processes, - but the break is actually a wow64 breakpoint. CDB is configured to ignore these - breakpoints, because they also appear on module loading. - Therefore we need helper executables (win(32/64)interrupt.exe) on Windows 64 bit calling - DebugBreakProcess from the correct system. - - DebugBreak matrix for windows - - Api = UseDebugBreakApi - Win64 = UseWin64Interrupt - Win32 = UseWin32Interrupt - N/A = This configuration is not possible - - | Windows 32bit | Windows 64bit - | QtCreator 32bit | QtCreator 32bit | QtCreator 64bit - | Inferior 32bit | Inferior 32bit | Inferior 64bit | Inferior 32bit | Inferior 64bit | -----------|-----------------|-----------------|-----------------|-----------------|----------------| -CDB 32bit | Api | Api | NA | Win32 | NA | - 64bit | NA | Win64 | Win64 | Api | Api | -----------|-----------------|-----------------|-----------------|-----------------|----------------| -GDB 32bit | Api | Api | NA | Win32 | NA | - 64bit | NA | Api | Win64 | Win32 | Api | -----------|-----------------|-----------------|-----------------|-----------------|----------------| - -*/ - - DebugBreakApi breakApi = UseDebugBreakApi; -#ifdef Q_OS_WIN64 - if ((engineType == GdbEngineType && isWow64Process(inferior)) - || (engineType == CdbEngineType && !engineExecutableIs64Bit)) { - breakApi = UseWin32Interrupt; - } -#else - if (isWow64Process(GetCurrentProcess()) - && ((engineType == CdbEngineType && engineExecutableIs64Bit) - || (engineType == GdbEngineType && !isWow64Process(inferior)))) { - breakApi = UseWin64Interrupt; - } -#endif - if (breakApi == UseDebugBreakApi) { - ok = DebugBreakProcess(inferior); - if (!ok) - *errorMessage = "DebugBreakProcess failed: " + Utils::winErrorMessage(GetLastError()); - } else { - const QString executable = breakApi == UseWin32Interrupt - ? QCoreApplication::applicationDirPath() + "/win32interrupt.exe" - : QCoreApplication::applicationDirPath() + "/win64interrupt.exe"; - if (!QFileInfo::exists(executable)) { - *errorMessage = QString::fromLatin1( - "%1 does not exist. If you have built %2 " - "on your own, checkout " - "https://code.qt.io/cgit/qt-creator/binary-artifacts.git/.") - .arg(QDir::toNativeSeparators(executable), - QGuiApplication::applicationDisplayName()); - break; - } - switch (QProcess::execute(executable, QStringList(QString::number(pID)))) { - case -2: - *errorMessage = QString::fromLatin1("Cannot start %1. Check src\\tools\\win64interrupt\\win64interrupt.c for more information."). - arg(QDir::toNativeSeparators(executable)); - break; - case 0: - ok = true; - break; - default: - *errorMessage = QDir::toNativeSeparators(executable) - + " could not break the process."; - break; - } - break; - } - } while (false); if (inferior != NULL) CloseHandle(inferior); if (!ok) @@ -159,8 +54,7 @@ GDB 32bit | Api | Api | NA | Win32 #include #include -bool Debugger::Internal::interruptProcess(qint64 pID, int /* engineType */, - QString *errorMessage, const bool /*engineExecutableIs64Bit*/) +bool Debugger::Internal::interruptProcess(qint64 pID, QString *errorMessage) { if (pID <= 0) { *errorMessage = msgCannotInterrupt(pID, QString::fromLatin1("Invalid process id.")); diff --git a/src/plugins/debugger/procinterrupt.h b/src/plugins/debugger/procinterrupt.h index c7872ed2e42..ef4d20300db 100644 --- a/src/plugins/debugger/procinterrupt.h +++ b/src/plugins/debugger/procinterrupt.h @@ -7,7 +7,6 @@ namespace Debugger::Internal { -bool interruptProcess(qint64 pID, int engineType, QString *errorMessage, - const bool engineExecutableIs64Bit = false); +bool interruptProcess(qint64 pID, QString *errorMessage); } // Debugger::Internal diff --git a/src/plugins/projectexplorer/devicesupport/desktopprocesssignaloperation.cpp b/src/plugins/projectexplorer/devicesupport/desktopprocesssignaloperation.cpp index 70412124462..773f4d3bca5 100644 --- a/src/plugins/projectexplorer/devicesupport/desktopprocesssignaloperation.cpp +++ b/src/plugins/projectexplorer/devicesupport/desktopprocesssignaloperation.cpp @@ -102,90 +102,20 @@ void DesktopProcessSignalOperation::killProcessSilently(qint64 pid) void DesktopProcessSignalOperation::interruptProcessSilently(qint64 pid) { #ifdef Q_OS_WIN - enum SpecialInterrupt { NoSpecialInterrupt, Win32Interrupt, Win64Interrupt }; - - bool is64BitSystem = is64BitWindowsSystem(); - SpecialInterrupt si = NoSpecialInterrupt; - if (is64BitSystem) - si = is64BitWindowsBinary(m_debuggerCommand) ? Win64Interrupt : Win32Interrupt; - /* - Windows 64 bit has a 32 bit subsystem (WOW64) which makes it possible to run a - 32 bit application inside a 64 bit environment. - When GDB is used DebugBreakProcess must be called from the same system (32/64 bit) running - the inferior. If CDB is used we could in theory break wow64 processes, - but the break is actually a wow64 breakpoint. CDB is configured to ignore these - breakpoints, because they also appear on module loading. - Therefore we need helper executables (win(32/64)interrupt.exe) on Windows 64 bit calling - DebugBreakProcess from the correct system. - - DebugBreak matrix for windows - - Api = UseDebugBreakApi - Win64 = UseWin64InterruptHelper - Win32 = UseWin32InterruptHelper - N/A = This configuration is not possible - - | Windows 32bit | Windows 64bit - | QtCreator 32bit | QtCreator 32bit | QtCreator 64bit - | Inferior 32bit | Inferior 32bit | Inferior 64bit | Inferior 32bit | Inferior 64bit -----------|-----------------|-----------------|-----------------|-----------------|---------------- -CDB 32bit | Api | Api | N/A | Win32 | N/A - 64bit | N/A | Win64 | Win64 | Api | Api -----------|-----------------|-----------------|-----------------|-----------------|---------------- -GDB 32bit | Api | Api | N/A | Win32 | N/A - 64bit | N/A | N/A | Win64 | N/A | Api -----------|-----------------|-----------------|-----------------|-----------------|---------------- - - */ HANDLE inferior = NULL; - do { - const DWORD rights = PROCESS_QUERY_INFORMATION|PROCESS_SET_INFORMATION - |PROCESS_VM_OPERATION|PROCESS_VM_WRITE|PROCESS_VM_READ - |PROCESS_DUP_HANDLE|PROCESS_TERMINATE|PROCESS_CREATE_THREAD|PROCESS_SUSPEND_RESUME; - inferior = OpenProcess(rights, FALSE, pid); - if (inferior == NULL) { - appendMsgCannotInterrupt(pid, Tr::tr("Cannot open process: %1") - + winErrorMessage(GetLastError())); - break; - } - bool creatorIs64Bit = is64BitWindowsBinary( - FilePath::fromUserInput(QCoreApplication::applicationFilePath())); - if (!is64BitSystem - || si == NoSpecialInterrupt - || (si == Win64Interrupt && creatorIs64Bit) - || (si == Win32Interrupt && !creatorIs64Bit)) { - if (!DebugBreakProcess(inferior)) { - appendMsgCannotInterrupt(pid, Tr::tr("DebugBreakProcess failed:") - + QLatin1Char(' ') + winErrorMessage(GetLastError())); - } - } else if (si == Win32Interrupt || si == Win64Interrupt) { - QString executable = QCoreApplication::applicationDirPath(); - executable += si == Win32Interrupt - ? QLatin1String("/win32interrupt.exe") - : QLatin1String("/win64interrupt.exe"); - if (!QFileInfo::exists(executable)) { - appendMsgCannotInterrupt(pid, - Tr::tr("%1 does not exist. If you built %2 " - "yourself, check out https://code.qt.io/cgit/" - "qt-creator/binary-artifacts.git/.") - .arg(QDir::toNativeSeparators(executable), - QGuiApplication::applicationDisplayName())); - } - switch (QProcess::execute(executable, QStringList(QString::number(pid)))) { - case -2: - appendMsgCannotInterrupt(pid, Tr::tr( - "Cannot start %1. Check src\\tools\\win64interrupt\\win64interrupt.c " - "for more information.").arg(QDir::toNativeSeparators(executable))); - break; - case 0: - break; - default: - appendMsgCannotInterrupt(pid, QDir::toNativeSeparators(executable) - + QLatin1Char(' ') + Tr::tr("could not break the process.")); - break; - } - } - } while (false); + const DWORD rights = PROCESS_QUERY_INFORMATION | PROCESS_SET_INFORMATION | PROCESS_VM_OPERATION + | PROCESS_VM_WRITE | PROCESS_VM_READ | PROCESS_DUP_HANDLE + | PROCESS_TERMINATE | PROCESS_CREATE_THREAD | PROCESS_SUSPEND_RESUME; + inferior = OpenProcess(rights, FALSE, pid); + if (inferior == NULL) { + appendMsgCannotInterrupt( + pid, Tr::tr("Cannot open process: %1") + winErrorMessage(GetLastError())); + } else if (!DebugBreakProcess(inferior)) { + appendMsgCannotInterrupt( + pid, + Tr::tr("DebugBreakProcess failed:") + QLatin1Char(' ') + + winErrorMessage(GetLastError())); + } if (inferior != NULL) CloseHandle(inferior); #else From 670b4ec72987e6fb37ecc7e9e7dd0780ff8e9168 Mon Sep 17 00:00:00 2001 From: David Schulz Date: Tue, 11 Jun 2024 11:47:19 +0200 Subject: [PATCH 13/24] Debugger: remove DebuggerRunTool::setUseCtrlCStub The ctrl c stub is now used by default. Change-Id: I802e8a4bd694bc98e8c4535875e9f2791d9dd5e9 Reviewed-by: hjk --- src/plugins/debugger/debuggerengine.h | 3 --- src/plugins/debugger/debuggerruncontrol.cpp | 5 ----- src/plugins/debugger/debuggerruncontrol.h | 1 - src/plugins/qnx/qnxdebugsupport.cpp | 2 -- 4 files changed, 11 deletions(-) diff --git a/src/plugins/debugger/debuggerengine.h b/src/plugins/debugger/debuggerengine.h index b5e8a3cba8d..6b264911cc4 100644 --- a/src/plugins/debugger/debuggerengine.h +++ b/src/plugins/debugger/debuggerengine.h @@ -125,9 +125,6 @@ public: // Used by Valgrind QStringList expectedSignals; - // For QNX debugging - bool useCtrlCStub = false; - // Used by Android to avoid false positives on warnOnRelease bool skipExecutableValidation = false; bool useTargetAsync = false; diff --git a/src/plugins/debugger/debuggerruncontrol.cpp b/src/plugins/debugger/debuggerruncontrol.cpp index 5688ff191ad..2f980f7fdc4 100644 --- a/src/plugins/debugger/debuggerruncontrol.cpp +++ b/src/plugins/debugger/debuggerruncontrol.cpp @@ -276,11 +276,6 @@ void DebuggerRunTool::setSkipExecutableValidation(bool on) m_runParameters.skipExecutableValidation = on; } -void DebuggerRunTool::setUseCtrlCStub(bool on) -{ - m_runParameters.useCtrlCStub = on; -} - void DebuggerRunTool::setBreakOnMain(bool on) { m_runParameters.breakOnMain = on; diff --git a/src/plugins/debugger/debuggerruncontrol.h b/src/plugins/debugger/debuggerruncontrol.h index 39fb7e9507f..bfd53299a1b 100644 --- a/src/plugins/debugger/debuggerruncontrol.h +++ b/src/plugins/debugger/debuggerruncontrol.h @@ -100,7 +100,6 @@ protected: void setRemoteChannel(const QUrl &url); void setUseTargetAsync(bool on); void setSkipExecutableValidation(bool on); - void setUseCtrlCStub(bool on); void setIosPlatform(const QString &platform); void setDeviceSymbolsRoot(const QString &deviceSymbolsRoot); diff --git a/src/plugins/qnx/qnxdebugsupport.cpp b/src/plugins/qnx/qnxdebugsupport.cpp index 27c26e269c0..322c3553071 100644 --- a/src/plugins/qnx/qnxdebugsupport.cpp +++ b/src/plugins/qnx/qnxdebugsupport.cpp @@ -126,7 +126,6 @@ public: setStartMode(AttachToRemoteServer); setCloseMode(KillAtClose); - setUseCtrlCStub(true); setSolibSearchPath(FileUtils::toFilePathList(searchPaths(k))); if (auto qtVersion = dynamic_cast(QtSupport::QtKitAspect::qtVersion(k))) { setSysRoot(qtVersion->qnxTarget()); @@ -196,7 +195,6 @@ public: { setId("QnxAttachDebugSupport"); setUsePortsGatherer(isCppDebugging(), isQmlDebugging()); - setUseCtrlCStub(true); if (isCppDebugging()) { auto pdebugRunner = new PDebugRunner(runControl, portsGatherer()); From 363e9b4c1a0cdb9c359a285d946e5cd3f03b49d2 Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 11 Jun 2024 13:52:26 +0200 Subject: [PATCH 14/24] Debugger: Drop some Python 2 leftovers Change-Id: Id120abaadb23af4139fc126b14a37932f6d630ea Reviewed-by: Christian Stenger --- share/qtcreator/debugger/dumper.py | 19 +++---------------- share/qtcreator/debugger/lldbbridge.py | 19 +++---------------- 2 files changed, 6 insertions(+), 32 deletions(-) diff --git a/share/qtcreator/debugger/dumper.py b/share/qtcreator/debugger/dumper.py index 58525df2f29..eb45d918be4 100644 --- a/share/qtcreator/debugger/dumper.py +++ b/share/qtcreator/debugger/dumper.py @@ -736,9 +736,6 @@ class DumperBase(): # Hex decoding operating on str, return str. @staticmethod def hexdecode(s, encoding='utf8'): - if sys.version_info[0] == 2: - # For python2 we need an extra str() call to return str instead of unicode - return str(s.decode('hex').decode(encoding)) return bytes.fromhex(s).decode(encoding) # Hex encoding operating on str or bytes, return str. @@ -746,10 +743,6 @@ class DumperBase(): def hexencode(s): if s is None: s = '' - if sys.version_info[0] == 2: - if isinstance(s, buffer): - return bytes(s).encode('hex') - return s.encode('hex') if isinstance(s, str): s = s.encode('utf8') return hexencode_(s) @@ -2727,10 +2720,7 @@ typename)) try: if funcname.startswith('qdump__'): typename = funcname[7:] - if sys.version_info > (3,): - spec = inspect.getfullargspec(function) - else: - spec = inspect.getargspec(function) + spec = inspect.getfullargspec(function) if len(spec.args) == 2: self.qqDumpers[typename] = function elif len(spec.args) == 3 and len(spec.defaults) == 1: @@ -2777,11 +2767,8 @@ typename)) def reloadDumpers(self, args): for mod in self.dumpermodules: m = sys.modules[mod] - if sys.version_info[0] >= 3: - import importlib - importlib.reload(m) - else: - reload(m) + import importlib + importlib.reload(m) self.setupDumpers(args) def loadDumpers(self, args): diff --git a/share/qtcreator/debugger/lldbbridge.py b/share/qtcreator/debugger/lldbbridge.py index 96c149ea025..3f7ec792a61 100644 --- a/share/qtcreator/debugger/lldbbridge.py +++ b/share/qtcreator/debugger/lldbbridge.py @@ -18,11 +18,7 @@ sys.path.insert(1, os.path.dirname(os.path.abspath(inspect.getfile(inspect.curre # Simplify development of this module by reloading deps if 'dumper' in sys.modules: - if sys.version_info[0] >= 3: - if sys.version_info[1] > 3: - from importlib import reload - else: - def reload(m): print('Unsupported Python version - not reloading %s' % str(m)) + from importlib import reload reload(sys.modules['dumper']) from dumper import DumperBase, SubItem, Children, TopLevelItem @@ -34,16 +30,10 @@ from dumper import DumperBase, SubItem, Children, TopLevelItem ####################################################################### qqWatchpointOffset = 10000 -_c_str_trans = None - -if sys.version_info[0] >= 3: - _c_str_trans = str.maketrans({"\n": "\\n", '"':'\\"', "\\":"\\\\"}) +_c_str_trans = str.maketrans({"\n": "\\n", '"':'\\"', "\\":"\\\\"}) def toCString(s): - if _c_str_trans is not None: - return str(s).translate(_c_str_trans) - else: - return str(s).replace('\\', '\\\\').replace('\n', '\\n').replace('"', '\\"') + return str(s).translate(_c_str_trans) def fileNameAsString(file): return toCString(file) if file.IsValid() else '' @@ -2360,9 +2350,6 @@ class SummaryProvider(LogMixin): if encoding in text_encodings: try: decodedValue = Dumper.hexdecode(summaryValue, encoding) - # LLDB expects UTF-8 for python 2 - if sys.version_info[0] < 3: - return "\"%s\"" % (decodedValue.encode('utf8')) return '"' + decodedValue + '"' except: return "" % (summaryValue, encoding, sys.exc_info()[1]) From 804a890a005463b5d464060899b69594ab2cb89b Mon Sep 17 00:00:00 2001 From: David Schulz Date: Tue, 11 Jun 2024 15:48:33 +0200 Subject: [PATCH 15/24] Debugger: fix QStack and QDateTime dumper amends 3aee50f5fd9ebd46c70bed9b0e7343f90afb6603 Change-Id: Iaa6666eb6c59f88572add6ae79ef942643ba38d4 Reviewed-by: hjk --- share/qtcreator/debugger/qttypes.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/share/qtcreator/debugger/qttypes.py b/share/qtcreator/debugger/qttypes.py index a9220636855..1b38223c2e1 100644 --- a/share/qtcreator/debugger/qttypes.py +++ b/share/qtcreator/debugger/qttypes.py @@ -312,7 +312,7 @@ def qdump__QDateTime(d, value): # {sharedref(4), ... base = d.extractPointer(value) is32bit = d.ptrSize() == 4 - if qtVersionAtLeast(0x050200): + if d.qtVersionAtLeast(0x050200): tiVersion = d.qtTypeInfoVersion() #DumperBase.warn('TI VERSION: %s' % tiVersion) if tiVersion is None: @@ -1713,7 +1713,7 @@ def qform__QStack(): def qdump__QStack(d, value): - if d.qtVersionVersionAtLeast(0x060000): + if d.qtVersionAtLeast(0x060000): qdump__QList(d, value) else: qdump__QVector(d, value) From 77b44bcb00458138cbe1591fc82a7f841319e4a3 Mon Sep 17 00:00:00 2001 From: Marcus Tillmanns Date: Tue, 11 Jun 2024 07:36:25 +0200 Subject: [PATCH 16/24] LuaLC: Register Settings type Change-Id: I58b3817e83c598b62e0ae5e61c21043d2c3290a7 Reviewed-by: David Schulz --- .../languageclient/lualanguageclient/lualanguageclient.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/plugins/languageclient/lualanguageclient/lualanguageclient.cpp b/src/plugins/languageclient/lualanguageclient/lualanguageclient.cpp index 67c0cf893a2..c9a12900230 100644 --- a/src/plugins/languageclient/lualanguageclient/lualanguageclient.cpp +++ b/src/plugins/languageclient/lualanguageclient/lualanguageclient.cpp @@ -548,6 +548,13 @@ static void registerLuaApi() // ... then register the settings. LanguageClientManager::registerClientSettings(client); + // and the client type. + ClientType type; + type.id = client->m_settingsTypeId; + type.name = luaClient->m_name; + type.userAddable = false; + LanguageClientSettings::registerClientType(type); + return luaClient; }); From f477ede697c67c0716232963298a6e9d218ed8d6 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Thu, 30 May 2024 16:18:17 +0200 Subject: [PATCH 17/24] CppEditor: Make header guard naming user-configurable Fixes: QTCREATORBUG-25117 Change-Id: I732e9a8f146b4d6a346492141ec364a99f167b94 Reviewed-by: David Schulz --- src/libs/utils/codegeneration.cpp | 17 --- src/libs/utils/codegeneration.h | 3 - src/plugins/clangtools/clangtoolrunner.cpp | 1 + src/plugins/cppeditor/cppeditorplugin.cpp | 2 +- src/plugins/cppeditor/cppfilesettingspage.cpp | 124 +++++++++++++++--- src/plugins/cppeditor/cppfilesettingspage.h | 7 +- src/plugins/cppeditor/cpptoolsjsextension.cpp | 2 +- src/plugins/cppeditor/cpptoolsreuse.cpp | 5 + src/plugins/cppeditor/cpptoolsreuse.h | 4 +- .../quickfixes/moveclasstoownfile.cpp | 2 +- .../qtdesignerformclasscodegenerator.cpp | 4 +- 11 files changed, 130 insertions(+), 41 deletions(-) diff --git a/src/libs/utils/codegeneration.cpp b/src/libs/utils/codegeneration.cpp index 8842023a239..ad3b8bad18f 100644 --- a/src/libs/utils/codegeneration.cpp +++ b/src/libs/utils/codegeneration.cpp @@ -29,23 +29,6 @@ QTCREATOR_UTILS_EXPORT QString fileNameToCppIdentifier(const QString &s) return rc; } -QTCREATOR_UTILS_EXPORT QString headerGuard(const QString &file) -{ - return headerGuard(file, QStringList()); -} - -QTCREATOR_UTILS_EXPORT QString headerGuard(const QString &file, const QStringList &namespaceList) -{ - const QChar underscore = QLatin1Char('_'); - QString rc; - for (int i = 0; i < namespaceList.count(); i++) - rc += namespaceList.at(i).toUpper() + underscore; - - const QFileInfo fi(file); - rc += fileNameToCppIdentifier(fi.fileName()).toUpper(); - return rc; -} - QTCREATOR_UTILS_EXPORT void writeIncludeFileDirective(const QString &file, bool globalInclude, QTextStream &str) diff --git a/src/libs/utils/codegeneration.h b/src/libs/utils/codegeneration.h index 9ea0bb28c7e..e1c297eb92c 100644 --- a/src/libs/utils/codegeneration.h +++ b/src/libs/utils/codegeneration.h @@ -17,9 +17,6 @@ namespace Utils { // or replacing them by an underscore). QTCREATOR_UTILS_EXPORT QString fileNameToCppIdentifier(const QString &s); -QTCREATOR_UTILS_EXPORT QString headerGuard(const QString &file); -QTCREATOR_UTILS_EXPORT QString headerGuard(const QString &file, const QStringList &namespaceList); - QTCREATOR_UTILS_EXPORT void writeIncludeFileDirective(const QString &file, bool globalInclude, diff --git a/src/plugins/clangtools/clangtoolrunner.cpp b/src/plugins/clangtools/clangtoolrunner.cpp index c91d9e9cfa7..08858a0498e 100644 --- a/src/plugins/clangtools/clangtoolrunner.cpp +++ b/src/plugins/clangtools/clangtoolrunner.cpp @@ -10,6 +10,7 @@ #include #include +#include #include #include #include diff --git a/src/plugins/cppeditor/cppeditorplugin.cpp b/src/plugins/cppeditor/cppeditorplugin.cpp index 63122a538b3..bd8d7331711 100644 --- a/src/plugins/cppeditor/cppeditorplugin.cpp +++ b/src/plugins/cppeditor/cppeditorplugin.cpp @@ -227,7 +227,7 @@ void CppEditorPlugin::initialize() void CppEditorPlugin::extensionsInitialized() { setupCppQuickFixProjectPanel(); - setupCppFileSettings(); + setupCppFileSettings(*this); setupCppCodeModelProjectSettingsPanel(); if (CppModelManager::isClangCodeModelActive()) { diff --git a/src/plugins/cppeditor/cppfilesettingspage.cpp b/src/plugins/cppeditor/cppfilesettingspage.cpp index 3579e0b5f21..a5c01b400b1 100644 --- a/src/plugins/cppeditor/cppfilesettingspage.cpp +++ b/src/plugins/cppeditor/cppfilesettingspage.cpp @@ -6,15 +6,19 @@ #include "cppeditortr.h" #include "cppheadersource.h" +#include + #include #include #include #include +#include #include #include #include +#include #include #include #include @@ -29,10 +33,30 @@ #include #include +#ifdef WITH_TESTS +#include +#endif + using namespace ProjectExplorer; using namespace Utils; namespace CppEditor::Internal { +namespace { +class HeaderGuardExpander : public MacroExpander +{ +public: + HeaderGuardExpander(const FilePath &filePath) : m_filePath(filePath) + { + setDisplayName(Tr::tr("Header file variables")); + registerFileVariables("Header", Tr::tr("Header file"), [this] { + return m_filePath; + }); + } + +private: + const FilePath m_filePath; +}; +} // namespace const char projectSettingsKeyC[] = "CppEditorFileNames"; const char useGlobalKeyC[] = "UseGlobal"; @@ -44,6 +68,7 @@ const char headerSearchPathsKeyC[] = "HeaderSearchPaths"; const char sourceSearchPathsKeyC[] = "SourceSearchPaths"; const char headerPragmaOnceC[] = "HeaderPragmaOnce"; const char licenseTemplatePathKeyC[] = "LicenseTemplate"; +const char headerGuardTemplateKeyC[] = "HeaderGuardTemplate"; const char *licenseTemplateTemplate = QT_TRANSLATE_NOOP("QtC::CppEditor", "/**************************************************************************\n" @@ -67,6 +92,7 @@ void CppFileSettings::toSettings(QtcSettings *s) const s->setValueWithDefault(headerPragmaOnceC, headerPragmaOnce, def.headerPragmaOnce); s->setValueWithDefault(licenseTemplatePathKeyC, licenseTemplatePath.toSettings(), def.licenseTemplatePath.toSettings()); + s->setValueWithDefault(headerGuardTemplateKeyC, headerGuardTemplate, def.headerGuardTemplate); s->endGroup(); } @@ -84,6 +110,7 @@ void CppFileSettings::fromSettings(QtcSettings *s) headerPragmaOnce = s->value(headerPragmaOnceC, def.headerPragmaOnce).toBool(); licenseTemplatePath = FilePath::fromSettings(s->value(licenseTemplatePathKeyC, def.licenseTemplatePath.toSettings())); + headerGuardTemplate = s->value(headerGuardTemplateKeyC, def.headerGuardTemplate).toString(); s->endGroup(); } @@ -124,6 +151,7 @@ bool CppFileSettings::equals(const CppFileSettings &rhs) const && sourceSuffix == rhs.sourceSuffix && headerSearchPaths == rhs.headerSearchPaths && sourceSearchPaths == rhs.sourceSearchPaths + && headerGuardTemplate == rhs.headerGuardTemplate && licenseTemplatePath == rhs.licenseTemplatePath; } @@ -237,6 +265,11 @@ QString CppFileSettings::licenseTemplate() const return license; } +QString CppFileSettings::headerGuard(const Utils::FilePath &headerFilePath) const +{ + return HeaderGuardExpander(headerFilePath).expand(headerGuardTemplate); +} + // ------------------ CppFileSettingsWidget class CppFileSettingsWidget final : public Core::IOptionsPageWidget @@ -269,6 +302,8 @@ private: QLineEdit *m_sourcePrefixesEdit = nullptr; QCheckBox *m_lowerCaseFileNamesCheckBox = nullptr; PathChooser *m_licenseTemplatePathChooser = nullptr; + StringAspect m_headerGuardAspect; + HeaderGuardExpander m_headerGuardExpander{{}}; }; CppFileSettingsWidget::CppFileSettingsWidget(CppFileSettings *settings) @@ -276,7 +311,7 @@ CppFileSettingsWidget::CppFileSettingsWidget(CppFileSettings *settings) , m_headerSuffixComboBox(new QComboBox) , m_headerSearchPathsEdit(new QLineEdit) , m_headerPrefixesEdit(new QLineEdit) - , m_headerPragmaOnceCheckBox(new QCheckBox(Tr::tr("Use \"#pragma once\" instead of \"#ifndef\" guards"))) + , m_headerPragmaOnceCheckBox(new QCheckBox(Tr::tr("Use \"#pragma once\" instead"))) , m_sourceSuffixComboBox(new QComboBox) , m_sourceSearchPathsEdit(new QLineEdit) , m_sourcePrefixesEdit(new QLineEdit) @@ -301,6 +336,8 @@ CppFileSettingsWidget::CppFileSettingsWidget(CppFileSettings *settings) m_sourcePrefixesEdit->setToolTip(Tr::tr("Comma-separated list of source prefixes.\n" "\n" "These prefixes are used in addition to current file name on Switch Header/Source.")); + m_headerGuardAspect.setDisplayStyle(Utils::StringAspect::LineEditDisplay); + m_headerGuardAspect.setMacroExpander(&m_headerGuardExpander); using namespace Layouting; @@ -311,8 +348,8 @@ CppFileSettingsWidget::CppFileSettingsWidget(CppFileSettings *settings) Tr::tr("&Suffix:"), m_headerSuffixComboBox, st, br, Tr::tr("S&earch paths:"), m_headerSearchPathsEdit, br, Tr::tr("&Prefixes:"), m_headerPrefixesEdit, br, - Tr::tr("Include guards"), m_headerPragmaOnceCheckBox - } + Tr::tr("Include guard template:"), m_headerPragmaOnceCheckBox, m_headerGuardAspect + }, }, Group { title(Tr::tr("Sources")), @@ -361,12 +398,21 @@ CppFileSettingsWidget::CppFileSettingsWidget(CppFileSettings *settings) this, &CppFileSettingsWidget::userChange); connect(m_sourcePrefixesEdit, &QLineEdit::textEdited, this, &CppFileSettingsWidget::userChange); - connect(m_headerPragmaOnceCheckBox, &QCheckBox::stateChanged, - this, &CppFileSettingsWidget::userChange); connect(m_lowerCaseFileNamesCheckBox, &QCheckBox::stateChanged, this, &CppFileSettingsWidget::userChange); connect(m_licenseTemplatePathChooser, &PathChooser::textChanged, this, &CppFileSettingsWidget::userChange); + const auto updateHeaderGuardAspectState = [this] { + m_headerGuardAspect.setEnabled(!m_headerPragmaOnceCheckBox->isChecked()); + }; + connect(m_headerPragmaOnceCheckBox, &QCheckBox::stateChanged, + this, [this, updateHeaderGuardAspectState] { + updateHeaderGuardAspectState(); + emit userChange(); + }); + connect(&m_headerGuardAspect, &StringAspect::changed, + this, &CppFileSettingsWidget::userChange); + updateHeaderGuardAspectState(); } FilePath CppFileSettingsWidget::licenseTemplatePath() const @@ -417,6 +463,7 @@ void CppFileSettingsWidget::setSettings(const CppFileSettings &s) m_headerSearchPathsEdit->setText(s.headerSearchPaths.join(comma)); m_sourceSearchPathsEdit->setText(s.sourceSearchPaths.join(comma)); setLicenseTemplatePath(s.licenseTemplatePath); + m_headerGuardAspect.setValue(s.headerGuardTemplate); } CppFileSettings CppFileSettingsWidget::currentSettings() const @@ -431,6 +478,7 @@ CppFileSettings CppFileSettingsWidget::currentSettings() const rc.headerSearchPaths = trimmedPaths(m_headerSearchPathsEdit->text()); rc.sourceSearchPaths = trimmedPaths(m_sourceSearchPathsEdit->text()); rc.licenseTemplatePath = licenseTemplatePath(); + rc.headerGuardTemplate = m_headerGuardAspect.value(); return rc; } @@ -536,6 +584,8 @@ void CppFileSettingsForProject::loadSettings() m_customSettings.lowerCaseFiles).toBool(); m_customSettings.headerPragmaOnce = data.value(headerPragmaOnceC, m_customSettings.headerPragmaOnce).toBool(); + m_customSettings.headerGuardTemplate + = data.value(headerGuardTemplateKeyC, m_customSettings.headerGuardTemplate).toString(); m_customSettings.licenseTemplatePath = FilePath::fromSettings(data.value(licenseTemplatePathKeyC, m_customSettings.licenseTemplatePath.toSettings())); @@ -560,6 +610,7 @@ void CppFileSettingsForProject::saveSettings() data.insert(sourceSearchPathsKeyC, m_customSettings.sourceSearchPaths); data.insert(Constants::LOWERCASE_CPPFILES_KEY, m_customSettings.lowerCaseFiles); data.insert(headerPragmaOnceC, m_customSettings.headerPragmaOnce); + data.insert(headerGuardTemplateKeyC, m_customSettings.headerGuardTemplate); data.insert(licenseTemplatePathKeyC, m_customSettings.licenseTemplatePath.toSettings()); m_project->setNamedSettings(projectSettingsKeyC, data); } @@ -631,16 +682,6 @@ public: } }; -void setupCppFileSettings() -{ - static CppFileSettingsProjectPanelFactory theCppFileSettingsProjectPanelFactory; - - static CppFileSettingsPage theCppFileSettingsPage; - - globalCppFileSettings().fromSettings(Core::ICore::settings()); - globalCppFileSettings().addMimeInitializer(); -} - CppFileSettings &globalCppFileSettings() { // This is the global instance. There could be more. @@ -653,6 +694,59 @@ CppFileSettings cppFileSettingsForProject(ProjectExplorer::Project *project) return CppFileSettingsForProject(project).settings(); } +#ifdef WITH_TESTS +namespace { +class CppFileSettingsTest : public QObject +{ + Q_OBJECT + +private slots: + void testHeaderGuard_data() + { + QTest::addColumn("guardTemplate"); + QTest::addColumn("headerFile"); + QTest::addColumn("expectedGuard"); + + QTest::newRow("default template, .h") + << QString() << QString("/tmp/header.h") << QString("HEADER_H"); + QTest::newRow("default template, .hpp") + << QString() << QString("/tmp/header.hpp") << QString("HEADER_HPP"); + QTest::newRow("default template, two extensions") + << QString() << QString("/tmp/header.in.h") << QString("HEADER_IN_H"); + QTest::newRow("non-default template") + << QString("%{JS: '%{Header:FilePath}'.toUpperCase().replace(/[.]/, '_').replace(/[/]/g, '_')}") + << QString("/tmp/header.h") << QString("_TMP_HEADER_H"); + } + + void testHeaderGuard() + { + QFETCH(QString, guardTemplate); + QFETCH(QString, headerFile); + QFETCH(QString, expectedGuard); + + CppFileSettings settings; + if (!guardTemplate.isEmpty()) + settings.headerGuardTemplate = guardTemplate; + QCOMPARE(settings.headerGuard(FilePath::fromUserInput(headerFile)), expectedGuard); + } +}; +} // namespace +#endif // WITH_TESTS + +void setupCppFileSettings(ExtensionSystem::IPlugin &plugin) +{ + static CppFileSettingsProjectPanelFactory theCppFileSettingsProjectPanelFactory; + + static CppFileSettingsPage theCppFileSettingsPage; + + globalCppFileSettings().fromSettings(Core::ICore::settings()); + globalCppFileSettings().addMimeInitializer(); + +#ifdef WITH_TESTS + plugin.addTestCreator([] { return new CppFileSettingsTest; }); +#endif +} + } // namespace CppEditor::Internal #include diff --git a/src/plugins/cppeditor/cppfilesettingspage.h b/src/plugins/cppeditor/cppfilesettingspage.h index 5915b5383cf..044ac6fb450 100644 --- a/src/plugins/cppeditor/cppfilesettingspage.h +++ b/src/plugins/cppeditor/cppfilesettingspage.h @@ -9,6 +9,7 @@ #include +namespace ExtensionSystem { class IPlugin; } namespace ProjectExplorer { class Project; } namespace CppEditor::Internal { @@ -28,6 +29,7 @@ public: QDir::toNativeSeparators("../Src"), ".."}; Utils::FilePath licenseTemplatePath; + QString headerGuardTemplate = "%{JS: '%{Header:FileName}'.toUpperCase().replace(/[.]/g, '_')}"; bool headerPragmaOnce = false; bool lowerCaseFiles = Constants::LOWERCASE_CPPFILES_DEFAULT; @@ -39,6 +41,9 @@ public: // Convenience to return a license template completely formatted. QString licenseTemplate() const; + // Expanded headerGuardTemplate. + QString headerGuard(const Utils::FilePath &headerFilePath) const; + bool equals(const CppFileSettings &rhs) const; bool operator==(const CppFileSettings &s) const { return equals(s); } bool operator!=(const CppFileSettings &s) const { return !equals(s); } @@ -48,6 +53,6 @@ CppFileSettings &globalCppFileSettings(); CppFileSettings cppFileSettingsForProject(ProjectExplorer::Project *project); -void setupCppFileSettings(); +void setupCppFileSettings(ExtensionSystem::IPlugin &plugin); } // namespace CppEditor::Internal diff --git a/src/plugins/cppeditor/cpptoolsjsextension.cpp b/src/plugins/cppeditor/cpptoolsjsextension.cpp index c03a38ede2b..c3ed6e6286e 100644 --- a/src/plugins/cppeditor/cpptoolsjsextension.cpp +++ b/src/plugins/cppeditor/cpptoolsjsextension.cpp @@ -42,7 +42,7 @@ static QString fileName(const QString &path, const QString &extension) QString CppToolsJsExtension::headerGuard(const QString &in) const { - return Utils::headerGuard(in); + return fileSettings().headerGuard(Utils::FilePath::fromString(in)); } QString CppToolsJsExtension::licenseTemplate() const diff --git a/src/plugins/cppeditor/cpptoolsreuse.cpp b/src/plugins/cppeditor/cpptoolsreuse.cpp index 6e0802b4bbe..7be177c2c1b 100644 --- a/src/plugins/cppeditor/cpptoolsreuse.cpp +++ b/src/plugins/cppeditor/cpptoolsreuse.cpp @@ -358,6 +358,11 @@ CppCompletionAssistProcessor *getCppCompletionAssistProcessor() return new Internal::InternalCppCompletionAssistProcessor(); } +QString deriveHeaderGuard(const Utils::FilePath &filePath, ProjectExplorer::Project *project) +{ + return Internal::cppFileSettingsForProject(project).headerGuard(filePath); +} + bool fileSizeExceedsLimit(const FilePath &filePath, int sizeLimitInMb) { if (sizeLimitInMb <= 0) diff --git a/src/plugins/cppeditor/cpptoolsreuse.h b/src/plugins/cppeditor/cpptoolsreuse.h index 8b1da79113d..71aabab08df 100644 --- a/src/plugins/cppeditor/cpptoolsreuse.h +++ b/src/plugins/cppeditor/cpptoolsreuse.h @@ -6,7 +6,6 @@ #include "cppeditor_global.h" #include "clangdiagnosticconfig.h" -#include "compileroptionsbuilder.h" #include "projectpart.h" #include @@ -65,6 +64,9 @@ quickFixOperations(const TextEditor::AssistInterface *interface); CppCompletionAssistProcessor CPPEDITOR_EXPORT *getCppCompletionAssistProcessor(); +QString CPPEDITOR_EXPORT +deriveHeaderGuard(const Utils::FilePath &filePath, ProjectExplorer::Project *project); + enum class CacheUsage { ReadWrite, ReadOnly }; Utils::FilePath CPPEDITOR_EXPORT correspondingHeaderOrSource( diff --git a/src/plugins/cppeditor/quickfixes/moveclasstoownfile.cpp b/src/plugins/cppeditor/quickfixes/moveclasstoownfile.cpp index 4b83faaf2d4..ada2027971e 100644 --- a/src/plugins/cppeditor/quickfixes/moveclasstoownfile.cpp +++ b/src/plugins/cppeditor/quickfixes/moveclasstoownfile.cpp @@ -388,7 +388,7 @@ private: = Utils::transform(state->namespacePath, [&](const Namespace *ns) { return ov.prettyName(ns->name()); }); - const QString headerGuard = Utils::headerGuard(headerFileName); + const QString headerGuard = fileSettings.headerGuard(headerFilePath); if (fileSettings.headerPragmaOnce) { headerContent.append("#pragma once\n"); } else { diff --git a/src/plugins/designer/qtdesignerformclasscodegenerator.cpp b/src/plugins/designer/qtdesignerformclasscodegenerator.cpp index e0afdc45d97..d3937ff696d 100644 --- a/src/plugins/designer/qtdesignerformclasscodegenerator.cpp +++ b/src/plugins/designer/qtdesignerformclasscodegenerator.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -75,7 +76,8 @@ bool QtDesignerFormClassCodeGenerator::generateCpp(const FormClassWizardParamete const QString sourceLicense = CppEditor::AbstractEditorSupport::licenseTemplate( project, FilePath::fromString(parameters.sourceFile), parameters.className); // Include guards - const QString guard = Utils::headerGuard(parameters.headerFile); + const QString guard + = CppEditor::deriveHeaderGuard(FilePath::fromString(parameters.headerFile), project); const QString uiInclude = "ui_" + QFileInfo(parameters.uiFile).completeBaseName() + ".h"; From e47c797dee2affa8458373af6c87f23810d17c6e Mon Sep 17 00:00:00 2001 From: Marcus Tillmanns Date: Wed, 12 Jun 2024 08:25:48 +0200 Subject: [PATCH 18/24] LSP: Fix MarkedString fromJson fromJsonValue(...) (with T = MarkedString) always tried to convert the json value toObject() first. Which is wrong since it can be an object or a string. Fixes the broken hover text for the json language server. Change-Id: Id69b4270238bea7068936a7d2142f4f94918f96b Reviewed-by: David Schulz --- src/libs/languageserverprotocol/languagefeatures.cpp | 6 ++++++ src/libs/languageserverprotocol/languagefeatures.h | 3 +++ src/libs/languageserverprotocol/lsputils.h | 2 +- 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/libs/languageserverprotocol/languagefeatures.cpp b/src/libs/languageserverprotocol/languagefeatures.cpp index 30e2b6bd84a..0c76a3b1c03 100644 --- a/src/libs/languageserverprotocol/languagefeatures.cpp +++ b/src/libs/languageserverprotocol/languagefeatures.cpp @@ -261,6 +261,12 @@ DocumentHighlightsResult::DocumentHighlightsResult(const QJsonValue &value) } } +template<> +MarkedString fromJsonValue(const QJsonValue &value) +{ + return MarkedString(value); +} + MarkedString::MarkedString(const QJsonValue &value) { if (value.isObject()) diff --git a/src/libs/languageserverprotocol/languagefeatures.h b/src/libs/languageserverprotocol/languagefeatures.h index e5ca9df31d6..6a60ec3612f 100644 --- a/src/libs/languageserverprotocol/languagefeatures.h +++ b/src/libs/languageserverprotocol/languagefeatures.h @@ -52,6 +52,9 @@ public: operator QJsonValue() const; }; +template<> +LANGUAGESERVERPROTOCOL_EXPORT MarkedString fromJsonValue(const QJsonValue &value); + class LANGUAGESERVERPROTOCOL_EXPORT HoverContent : public std::variant, MarkupContent> { diff --git a/src/libs/languageserverprotocol/lsputils.h b/src/libs/languageserverprotocol/lsputils.h index 32e2bfa6b7e..a5178f813fd 100644 --- a/src/libs/languageserverprotocol/lsputils.h +++ b/src/libs/languageserverprotocol/lsputils.h @@ -68,7 +68,7 @@ public: if (value.isArray()) { QList values; values.reserve(value.toArray().count()); - for (auto arrayValue : value.toArray()) + for (const auto &arrayValue : value.toArray()) values << fromJsonValue(arrayValue); *this = values; } else { From 9ee39e514188a455687bfa262071e1afad460e16 Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Thu, 23 May 2024 13:55:50 +0200 Subject: [PATCH 19/24] Doc: Describe how to add optimized self-built Qt Fixes: QTCREATORBUG-30841 Change-Id: Id5c2fe0fcf925812b9abc8d8f53557aeeb917e32 Reviewed-by: hjk Reviewed-by: Christian Kandeler --- ...dit-cmake-configuration-self-built-qt.webp | Bin 0 -> 8410 bytes .../src/baremetal/creator-baremetal-dev.qdoc | 4 +- .../creator-projects-qt-versions.qdoc | 45 ++++++++++++------ 3 files changed, 34 insertions(+), 15 deletions(-) create mode 100644 doc/qtcreator/images/qtcreator-edit-cmake-configuration-self-built-qt.webp diff --git a/doc/qtcreator/images/qtcreator-edit-cmake-configuration-self-built-qt.webp b/doc/qtcreator/images/qtcreator-edit-cmake-configuration-self-built-qt.webp new file mode 100644 index 0000000000000000000000000000000000000000..820461039e9b2901c49b34f17f5762e961f638f4 GIT binary patch literal 8410 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 literal 0 HcmV?d00001 diff --git a/doc/qtcreator/src/baremetal/creator-baremetal-dev.qdoc b/doc/qtcreator/src/baremetal/creator-baremetal-dev.qdoc index 3df5faba46d..70ded6fc366 100644 --- a/doc/qtcreator/src/baremetal/creator-baremetal-dev.qdoc +++ b/doc/qtcreator/src/baremetal/creator-baremetal-dev.qdoc @@ -23,7 +23,9 @@ applications on them. \note If you use qmake to build the project and the device does not have - Qt libraries, you need a fake Qt installation. + Qt libraries, you need a Qt installation that meets the requirements in + \l{Self-built Qt versions}. In addition, the \c mkspecs directory needs + to be complete enough to parse .pro files. The following toolchains are supported for building applications: diff --git a/doc/qtcreator/src/projects/creator-only/creator-projects-qt-versions.qdoc b/doc/qtcreator/src/projects/creator-only/creator-projects-qt-versions.qdoc index 0b06e1d84c1..48958f8846e 100644 --- a/doc/qtcreator/src/projects/creator-only/creator-projects-qt-versions.qdoc +++ b/doc/qtcreator/src/projects/creator-only/creator-projects-qt-versions.qdoc @@ -108,28 +108,45 @@ To verify the installation of a particular Qt version, \QC calls \c {qmake -query} and checks that the directories referenced in the - output exist. When \QC complains about the installation of a self-built Qt - version, try running \c {make install} in the build directory to actually - install Qt into the configured location. If you installed Qt using the Qt - Installer, run \QMT to check for updates or to reinstall - the Qt version. + output exist. If you installed Qt using \QOI, run + \QMT to check for updates or to reinstall the Qt version. - \section1 Minimum requirements - If your build of Qt is incomplete but you still want to use qmake as build - system, you need to ensure the following minimum requirements to use that - setup with \QC. + \section2 Self-built Qt versions - \list 1 + To build projects with a self-built Qt version, add it as described in + \l{Set up new Qt versions}. + + Your Qt has to meet the following minimum requirements: + + \list \li qmake is an executable that understands the \c -query command-line argument. \li The \c bin and \c include directories have to exist. \QC fetches these directories by running \c{qmake -query}. - \li The \c mkspecs directory should be complete enough to parse .pro - files. \endlist - If your Qt version has no \c libQtCore.so, \QC cannot detect the ABI. + Add a kit for the Qt version and configure it for CMake. - \sa {kits-tab}{Kits} + \QC issues warnings if: + + \list + \li \c libQtCore.so is missing, so \QC cannot detect the ABI. + \li \c toolchain.cmake is missing. For example, you built Qt with the + \c -static option for an x86 platform. + \endlist + + Try the following: + + \list + \li Run \c {make install} in the build directory to install Qt into the + configured location. + \li Set the value of the \c CMAKE_PREFIX_PATH variable in \preferences > + \uicontrol Kits > \uicontrol Kits > \uicontrol {CMake Configuration} + to the location where you installed Qt. + \endlist + + \image qtcreator-edit-cmake-configuration-self-built-qt.webp {Setting the path to a self-built Qt} + + \sa {Manage Kits}{How To: Manage Kits}, {kits-tab}{Kits} */ From 6c6b01faa83a9341e0448a99c0581d1b88cdbe02 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Tue, 11 Jun 2024 17:24:18 +0200 Subject: [PATCH 20/24] qbs build: Fix building documentation qdoc needs a new environment variable these days. Change-Id: I29eb64c2d3ee7555fc99a928971eaccaac8317bf Reviewed-by: Christian Stenger --- qbs/imports/QtcDocumentation.qbs | 1 + 1 file changed, 1 insertion(+) diff --git a/qbs/imports/QtcDocumentation.qbs b/qbs/imports/QtcDocumentation.qbs index 3017114c8c4..c5ddf497206 100644 --- a/qbs/imports/QtcDocumentation.qbs +++ b/qbs/imports/QtcDocumentation.qbs @@ -12,6 +12,7 @@ Product { property string versionTag: qtc.qtcreator_version.replace(/\.|-/g, "") Qt.core.qdocEnvironment: [ + "GENERATED_ATTRIBUTIONS_DIR=" + product.buildDirectory, "IDE_DISPLAY_NAME=" + qtc.ide_display_name, "IDE_CASED_ID=" + qtc.ide_cased_id, "IDE_ID=" + qtc.ide_id, From e84a9bc3d5ca92a026f49664d03aeff77a2f3e18 Mon Sep 17 00:00:00 2001 From: David Schulz Date: Wed, 12 Jun 2024 10:34:43 +0200 Subject: [PATCH 21/24] WorkspaceProject: exclude user file and define scheme url by default Change-Id: I359682a0010a42f00591c103c93b7f41c7f987fd Reviewed-by: Marcus Tillmanns --- src/plugins/lua/wizards/plugin/project.json | 2 ++ src/plugins/projectexplorer/workspaceproject.cpp | 7 ++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/plugins/lua/wizards/plugin/project.json b/src/plugins/lua/wizards/plugin/project.json index f537bf2ea9d..b7879f50d77 100644 --- a/src/plugins/lua/wizards/plugin/project.json +++ b/src/plugins/lua/wizards/plugin/project.json @@ -1,4 +1,6 @@ { + "$schema": "https://download.qt.io/official_releases/qtcreator/latest/installer_source/jsonschemas/project.json", + "files.exclude": [".qtcreator/project.json.user"], "targets": [ { "name": "Qt Creator", diff --git a/src/plugins/projectexplorer/workspaceproject.cpp b/src/plugins/projectexplorer/workspaceproject.cpp index 5b0a92ba6c9..6cbb858921b 100644 --- a/src/plugins/projectexplorer/workspaceproject.cpp +++ b/src/plugins/projectexplorer/workspaceproject.cpp @@ -253,7 +253,12 @@ public: : Project(FOLDER_MIMETYPE, file.isDir() ? file / ".qtcreator" / "project.json" : file) { QTC_CHECK(projectFilePath().absolutePath().ensureWritableDir()); - QTC_CHECK(projectFilePath().ensureExistingFile()); + if (!projectFilePath().exists() && QTC_GUARD(projectFilePath().ensureExistingFile())) { + QJsonObject projectJson; + projectJson.insert("$schema", "https://download.qt.io/official_releases/qtcreator/latest/installer_source/jsonschemas/project.json"); + projectJson.insert(FILES_EXCLUDE_KEY, QJsonArray{QJsonValue(".qtcreator/project.json.user")}); + projectFilePath().writeFileContents(QJsonDocument(projectJson).toJson()); + } setId(Id::fromString(WORKSPACE_PROJECT_ID)); setDisplayName(projectDirectory().fileName()); From 9a06e1f65c25424696ad9a1ced5eec7560f30f80 Mon Sep 17 00:00:00 2001 From: David Schulz Date: Thu, 6 Jun 2024 15:01:42 +0200 Subject: [PATCH 22/24] Debugger: prefer 64 bit cdb and remove auto detected 32 bit cdb Change-Id: I57a4b0cb25a6d33478bc7a5cde9a427cfc5214c6 Reviewed-by: Christian Stenger --- src/plugins/debugger/debuggeritem.cpp | 7 +++++-- src/plugins/debugger/debuggeritemmanager.cpp | 6 ++++++ src/plugins/debugger/debuggerkitaspect.cpp | 9 +++++++++ 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/plugins/debugger/debuggeritem.cpp b/src/plugins/debugger/debuggeritem.cpp index c5b1bc7f6b6..dff784341a7 100644 --- a/src/plugins/debugger/debuggeritem.cpp +++ b/src/plugins/debugger/debuggeritem.cpp @@ -440,8 +440,11 @@ static DebuggerItem::MatchLevel matchSingle(const Abi &debuggerAbi, const Abi &t return matchOnMultiarch; } - if (debuggerAbi.wordWidth() == 64 && targetAbi.wordWidth() == 32) - return DebuggerItem::MatchesSomewhat; + if (debuggerAbi.wordWidth() == 64 && targetAbi.wordWidth() == 32) { + return HostOsInfo::isWindowsHost() && engineType == CdbEngineType + ? DebuggerItem::MatchesPerfectly + : DebuggerItem::MatchesSomewhat; + } if (debuggerAbi.wordWidth() != 0 && debuggerAbi.wordWidth() != targetAbi.wordWidth()) return matchOnMultiarch; diff --git a/src/plugins/debugger/debuggeritemmanager.cpp b/src/plugins/debugger/debuggeritemmanager.cpp index 4d9d663d0d0..23dcee4ee6a 100644 --- a/src/plugins/debugger/debuggeritemmanager.cpp +++ b/src/plugins/debugger/debuggeritemmanager.cpp @@ -783,6 +783,12 @@ void DebuggerItemModel::readDebuggers(const FilePath &fileName, bool isSystem) .arg(item.command().toUserOutput(), item.id().toString(), fileName.toUserOutput()); continue; } + if (item.engineType() == CdbEngineType + && Abi::abisOfBinary(item.command()).value(0).wordWidth() == 32) { + qWarning() << QString("32 bit CDB \"%1\" (%2) read from \"%3\" dropped since it is not supported anymore.") + .arg(item.command().toUserOutput(), item.id().toString(), fileName.toUserOutput()); + continue; + } // FIXME: During startup, devices are not yet available, so we cannot check if the file still exists. if (!item.command().needsDevice() && !item.command().isExecutableFile()) { qWarning() << QString("DebuggerItem \"%1\" (%2) read from \"%3\" dropped since the command is not executable.") diff --git a/src/plugins/debugger/debuggerkitaspect.cpp b/src/plugins/debugger/debuggerkitaspect.cpp index 10559a70840..15a3e8827c1 100644 --- a/src/plugins/debugger/debuggerkitaspect.cpp +++ b/src/plugins/debugger/debuggerkitaspect.cpp @@ -388,6 +388,15 @@ public: k->setValue(DebuggerKitAspect::id(), bestLevel != DebuggerItem::DoesNotMatch ? bestItem.id() : QVariant()); } + void fix(Kit *k) override + { + const QVariant id = k->value(DebuggerKitAspect::id()); + if (Utils::anyOf(DebuggerItemManager::debuggers(), Utils::equal(&DebuggerItem::id, id))) + return; + k->removeKeySilently(DebuggerKitAspect::id()); + setup(k); + } + KitAspect *createKitAspect(Kit *k) const override { return new Internal::DebuggerKitAspectImpl(k, this); From e9fd7e5c2c4056b8cbf5e0ad65ded3cf1834088c Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Mon, 10 Jun 2024 14:40:22 +0200 Subject: [PATCH 23/24] Make it possible to mark a plugin experimental but not disabledByDefault For plugins that are shipped by Qt Creator, it makes sense to disable experimental plugins by default. But for separately installed plugins it is weird that you first have to download and install them, and then also have to explicitly turn them on. Use that for AppStatisticsMonitor in the case that it is built and installed as a separate plugin. Change-Id: I12e979d2e088dc32380c2e2ae83ed2b7ef9276b0 Reviewed-by: Artem Sokolovskii Reviewed-by: Alessandro Portale --- src/libs/extensionsystem/pluginspec.cpp | 4 +--- src/plugins/appstatisticsmonitor/AppStatisticsMonitor.json.in | 1 + src/plugins/appstatisticsmonitor/CMakeLists.txt | 4 ++++ 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/libs/extensionsystem/pluginspec.cpp b/src/libs/extensionsystem/pluginspec.cpp index 18c8d11e78f..f7d72b80420 100644 --- a/src/libs/extensionsystem/pluginspec.cpp +++ b/src/libs/extensionsystem/pluginspec.cpp @@ -844,11 +844,9 @@ Utils::expected_str PluginSpecPrivate::readMetaData(const QJsonObject &dat value = metaData.value(QLatin1String(PLUGIN_DISABLED_BY_DEFAULT)); if (!value.isUndefined() && !value.isBool()) return reportError(msgValueIsNotABool(PLUGIN_DISABLED_BY_DEFAULT)); - enabledByDefault = !value.toBool(false); + enabledByDefault = !value.toBool(experimental || deprecated); qCDebug(pluginLog) << "enabledByDefault =" << enabledByDefault; - if (experimental || deprecated) - enabledByDefault = false; enabledBySettings = enabledByDefault; value = metaData.value(QLatin1String(PLUGIN_SOFTLOADABLE)); diff --git a/src/plugins/appstatisticsmonitor/AppStatisticsMonitor.json.in b/src/plugins/appstatisticsmonitor/AppStatisticsMonitor.json.in index 920b3ec31bb..757acf5052f 100644 --- a/src/plugins/appstatisticsmonitor/AppStatisticsMonitor.json.in +++ b/src/plugins/appstatisticsmonitor/AppStatisticsMonitor.json.in @@ -3,6 +3,7 @@ "Version" : "${IDE_VERSION}", "CompatVersion" : "${IDE_VERSION_COMPAT}", "Experimental" : true, + "DisabledByDefault" : ${APPSTATISTICSMONITOR_DISABLEDBYDEFAULT}, "Vendor" : "The Qt Company Ltd", "Copyright" : "(C) ${IDE_COPYRIGHT_YEAR} The Qt Company Ltd", "License" : [ "Commercial Usage", diff --git a/src/plugins/appstatisticsmonitor/CMakeLists.txt b/src/plugins/appstatisticsmonitor/CMakeLists.txt index 92ae05962c9..1e00a0afab3 100644 --- a/src/plugins/appstatisticsmonitor/CMakeLists.txt +++ b/src/plugins/appstatisticsmonitor/CMakeLists.txt @@ -13,6 +13,8 @@ set(CMAKE_CXX_EXTENSIONS OFF) find_package(Qt6 COMPONENTS Charts QUIET) +set(APPSTATISTICSMONITOR_DISABLEDBYDEFAULT "true") + if (NOT QT_CREATOR_API_DEFINED) # standalone build set(DESTINATION DESTINATION .) @@ -21,6 +23,8 @@ if (NOT QT_CREATOR_API_DEFINED) qtc_handle_compiler_cache_support() find_package(QtCreator COMPONENTS Core ProjectExplorer Utils REQUIRED) + + set(APPSTATISTICSMONITOR_DISABLEDBYDEFAULT "false") endif() From 0eed1b3efafabc6f0eb72c4959451b9d78298d23 Mon Sep 17 00:00:00 2001 From: Cristian Adam Date: Tue, 11 Jun 2024 19:21:47 +0200 Subject: [PATCH 24/24] CMake: Fix static build of Qt Creator The plugin class names were different, and this is important for static plugins because the symbols wouldn't be found at linking time. Change-Id: Ia2254e5ce811fe23daf12e445593980211b7cd47 Reviewed-by: Alessandro Portale --- src/plugins/designer/CMakeLists.txt | 2 +- src/plugins/qtapplicationmanager/CMakeLists.txt | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/plugins/designer/CMakeLists.txt b/src/plugins/designer/CMakeLists.txt index d9da4cfaf4d..c8f84ffb2df 100644 --- a/src/plugins/designer/CMakeLists.txt +++ b/src/plugins/designer/CMakeLists.txt @@ -25,7 +25,7 @@ else() endif() add_qtc_plugin(Designer - PLUGIN_CLASS FormEditorPlugin + PLUGIN_CLASS DesignerPlugin CONDITION TARGET Qt::DesignerComponentsPrivate AND TARGET Qt::Designer DEPENDS designerintegrationv2 Qt::Designer Qt::PrintSupport Qt::DesignerComponentsPrivate diff --git a/src/plugins/qtapplicationmanager/CMakeLists.txt b/src/plugins/qtapplicationmanager/CMakeLists.txt index a49279eba10..6241cb1de36 100644 --- a/src/plugins/qtapplicationmanager/CMakeLists.txt +++ b/src/plugins/qtapplicationmanager/CMakeLists.txt @@ -4,6 +4,7 @@ add_qtc_plugin(QtApplicationManagerIntegration PLUGIN_DEPENDS Core Debugger ProjectExplorer QtSupport RemoteLinux + PLUGIN_CLASS AppManagerPlugin DEPENDS Qt::Network Qt::Widgets ExtensionSystem Utils yaml-cpp SOURCES appmanagerconstants.h