From 7c1971e908d29ff42dd740d331220b2cdadfadc2 Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Mon, 5 Oct 2020 09:39:41 +0200 Subject: [PATCH 01/10] Doc: Point to the online docs from README.md To advertise the docs on GitHub. Task-number: QTCREATORBUG-21179 Change-Id: I39bac5cfb8f9749966c3b879b0a89c4e62d934f4 Reviewed-by: Eike Ziller --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index 1d3be2fbde5..0e59d2e79f9 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,14 @@ Qt Creator is a cross-platform, integrated development environment (IDE) for application developers to create applications for multiple desktop, embedded, and mobile device platforms. +The Qt Creator Manual is available at: + +https://doc.qt.io/qtcreator/index.html + +For an overview of the Qt Creator IDE, see: + +https://doc.qt.io/qtcreator/creator-overview.html + ## Supported Platforms The standalone binary packages support the following platforms: From 3a4ede2e1b6c6f09219d9adf90b1a0a1684695ab Mon Sep 17 00:00:00 2001 From: Jochen Seemann Date: Sun, 30 Dec 2018 20:42:22 +0100 Subject: [PATCH 02/10] Add support for Conan package manager Task-number: QTCREATORBUG-21785 Change-Id: I4b2dbcc16a2504efe9fdc9e31fa2ef14bba7c33c Reviewed-by: Kai Koehne Reviewed-by: Eike Ziller --- src/plugins/CMakeLists.txt | 1 + src/plugins/conan/CMakeLists.txt | 6 + src/plugins/conan/Conan.json.in | 20 ++ src/plugins/conan/conan.pro | 8 + src/plugins/conan/conan.qbs | 19 ++ src/plugins/conan/conan_dependencies.pri | 6 + src/plugins/conan/conaninstallstep.cpp | 252 +++++++++++++++++++++++ src/plugins/conan/conaninstallstep.h | 97 +++++++++ src/plugins/conan/conanplugin.cpp | 60 ++++++ src/plugins/conan/conanplugin.h | 49 +++++ src/plugins/plugins.pro | 3 +- src/plugins/plugins.qbs | 1 + 12 files changed, 521 insertions(+), 1 deletion(-) create mode 100644 src/plugins/conan/CMakeLists.txt create mode 100644 src/plugins/conan/Conan.json.in create mode 100644 src/plugins/conan/conan.pro create mode 100644 src/plugins/conan/conan.qbs create mode 100644 src/plugins/conan/conan_dependencies.pri create mode 100644 src/plugins/conan/conaninstallstep.cpp create mode 100644 src/plugins/conan/conaninstallstep.h create mode 100644 src/plugins/conan/conanplugin.cpp create mode 100644 src/plugins/conan/conanplugin.h diff --git a/src/plugins/CMakeLists.txt b/src/plugins/CMakeLists.txt index 70f8f42000b..86fd7096f2c 100644 --- a/src/plugins/CMakeLists.txt +++ b/src/plugins/CMakeLists.txt @@ -27,6 +27,7 @@ add_subdirectory(resourceeditor) add_subdirectory(tasklist) add_subdirectory(nim) add_subdirectory(incredibuild) +add_subdirectory(conan) # Level 4: (only depends on Level 3 and below) add_subdirectory(clangpchmanager) diff --git a/src/plugins/conan/CMakeLists.txt b/src/plugins/conan/CMakeLists.txt new file mode 100644 index 00000000000..fd19c478755 --- /dev/null +++ b/src/plugins/conan/CMakeLists.txt @@ -0,0 +1,6 @@ +add_qtc_plugin(Conan + PLUGIN_DEPENDS Core ProjectExplorer + SOURCES + conaninstallstep.cpp conaninstallstep.h + conanplugin.cpp conanplugin.h +) diff --git a/src/plugins/conan/Conan.json.in b/src/plugins/conan/Conan.json.in new file mode 100644 index 00000000000..ac2cfcd52ef --- /dev/null +++ b/src/plugins/conan/Conan.json.in @@ -0,0 +1,20 @@ +{ + \"Name\" : \"Conan\", + \"Version\" : \"$$QTCREATOR_VERSION\", + \"CompatVersion\" : \"$$QTCREATOR_COMPAT_VERSION\", + \"Vendor\" : \"Jochen Seemann\", + \"Copyright\" : \"(C) 2018 Jochen Seemann, (C) $$QTCREATOR_COPYRIGHT_YEAR The Qt Company Ltd\", + \"License\" : [ \"Commercial Usage\", + \"\", + \"Licensees holding valid Qt Commercial licenses may use this plugin in accordance with the Qt Commercial License Agreement provided with the Software or, alternatively, in accordance with the terms contained in a written agreement between you and The Qt Company.\", + \"\", + \"GNU General Public License Usage\", + \"\", + \"Alternatively, this plugin may be used under the terms of the GNU General Public License version 3 as published by the Free Software Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT included in the packaging of this plugin. Please review the following information to ensure the GNU General Public License requirements will be met: https://www.gnu.org/licenses/gpl-3.0.html.\" + ], + \"Category\" : \"Utilities\", + \"Experimental\" : true, + \"Description\" : \"Conan integration.\", + \"Url\" : \"http://www.qt.io\", + $$dependencyList +} diff --git a/src/plugins/conan/conan.pro b/src/plugins/conan/conan.pro new file mode 100644 index 00000000000..6fc42a8a62e --- /dev/null +++ b/src/plugins/conan/conan.pro @@ -0,0 +1,8 @@ +include(../../qtcreatorplugin.pri) + +SOURCES += \ + conaninstallstep.cpp \ + conanplugin.cpp +HEADERS += \ + conaninstallstep.h \ + conanplugin.h diff --git a/src/plugins/conan/conan.qbs b/src/plugins/conan/conan.qbs new file mode 100644 index 00000000000..8ed2f131d29 --- /dev/null +++ b/src/plugins/conan/conan.qbs @@ -0,0 +1,19 @@ +import qbs 1.0 + +QtcPlugin { + name: "Conan" + + Depends { name: "Qt.widgets" } + Depends { name: "Utils" } + + Depends { name: "Core" } + Depends { name: "ProjectExplorer" } + + files: [ + "conanplugin.h", + "conanplugin.cpp", + "conaninstallstep.h", + "conaninstallstep.cpp" + ] +} + diff --git a/src/plugins/conan/conan_dependencies.pri b/src/plugins/conan/conan_dependencies.pri new file mode 100644 index 00000000000..e9c05fe2e58 --- /dev/null +++ b/src/plugins/conan/conan_dependencies.pri @@ -0,0 +1,6 @@ +QTC_PLUGIN_NAME = Conan +QTC_LIB_DEPENDS += \ + utils +QTC_PLUGIN_DEPENDS += \ + coreplugin \ + projectexplorer diff --git a/src/plugins/conan/conaninstallstep.cpp b/src/plugins/conan/conaninstallstep.cpp new file mode 100644 index 00000000000..53770859e9f --- /dev/null +++ b/src/plugins/conan/conaninstallstep.cpp @@ -0,0 +1,252 @@ +/**************************************************************************** +** +** Copyright (C) 2018 Jochen Seemann +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "conaninstallstep.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +using namespace ProjectExplorer; +using namespace ProjectExplorer::Constants; +using namespace Utils; + +namespace ConanPackageManager { +namespace Internal { + +const char INSTALL_STEP_ID[] = "ConanPackageManager.InstallStep"; +const char INSTALL_STEP_CONANFILE_SUBDIR_KEY[] = "ConanPackageManager.InstallStep.ConanfileSubdir"; +const char INSTALL_STEP_ADDITIONAL_ARGUMENTS_KEY[] = "ConanPackageManager.InstallStep.AdditionalArguments"; + +ConanInstallStepFactory::ConanInstallStepFactory() +{ + registerStep(INSTALL_STEP_ID); + setDisplayName(ConanInstallStep::tr("conan install", "Install packages specified in Conanfile.txt")); +} + +ConanInstallStep::ConanInstallStep(BuildStepList *bsl, Utils::Id id) : AbstractProcessStep(bsl, id) +{ + setDefaultDisplayName(tr("conan install")); +} + +bool ConanInstallStep::init() +{ + BuildConfiguration *bc = buildConfiguration(); + QTC_ASSERT(bc, return false); + + QList tcList = ToolChainKitAspect::toolChains(target()->kit()); + if (tcList.isEmpty()) + emit addTask(Task::compilerMissingTask()); + + if (tcList.isEmpty() || !bc) { + emitFaultyConfigurationMessage(); + return false; + } + + ProcessParameters *pp = processParameters(); + Utils::Environment env = bc->environment(); + Utils::Environment::setupEnglishOutput(&env); + pp->setEnvironment(env); + pp->setWorkingDirectory(bc->buildDirectory()); + pp->setCommandLine(Utils::CommandLine("conan", arguments())); + + return AbstractProcessStep::init(); +} + +void ConanInstallStep::setupOutputFormatter(OutputFormatter *formatter) +{ + formatter->addLineParser(new GnuMakeParser()); + formatter->addLineParsers(kit()->createOutputParsers()); + formatter->addSearchDir(processParameters()->effectiveWorkingDirectory()); + AbstractProcessStep::setupOutputFormatter(formatter); +} + +BuildStepConfigWidget *ConanInstallStep::createConfigWidget() +{ + return new ConanInstallStepConfigWidget(this); +} + +bool ConanInstallStep::immutable() const +{ + return false; +} + +QStringList ConanInstallStep::arguments() const +{ + BuildConfiguration *bc = buildConfiguration(); + if (!bc) + bc = target()->activeBuildConfiguration(); + + if (!bc) + return {}; + + const Utils::FilePath conanFileDir = relativeSubdir().isEmpty() + ? bc->buildDirectory() + : bc->buildDirectory().pathAppended(relativeSubdir()); + + const QString buildType = bc->buildType() == BuildConfiguration::Release ? QString("Release") + : QString("Debug"); + const QString relativePath + = bc->project()->projectDirectory().relativeChildPath(conanFileDir).toString(); + QStringList installArguments; + installArguments << "install"; + if (!relativePath.isEmpty()) + installArguments << relativePath; + installArguments << "-s"; + installArguments << "build_type=" + buildType; + installArguments << conanFileDir.toString(); + installArguments << additionalArguments(); + return installArguments; +} + +QString ConanInstallStep::relativeSubdir() const +{ + return m_relativeSubdir; +} + +QStringList ConanInstallStep::additionalArguments() const +{ + return Utils::QtcProcess::splitArgs(m_additionalArguments); +} + +void ConanInstallStep::setRelativeSubdir(const QString &subdir) +{ + if (subdir == m_relativeSubdir) + return; + + m_relativeSubdir = subdir; + emit relativeSubdirChanged(subdir); +} + +void ConanInstallStep::setAdditionalArguments(const QString &list) +{ + if (list == m_additionalArguments) + return; + + m_additionalArguments = list; + + emit additionalArgumentsChanged(list); +} + +QVariantMap ConanInstallStep::toMap() const +{ + QVariantMap map = AbstractProcessStep::toMap(); + + map.insert(INSTALL_STEP_CONANFILE_SUBDIR_KEY, m_relativeSubdir); + map.insert(INSTALL_STEP_ADDITIONAL_ARGUMENTS_KEY, m_additionalArguments); + return map; +} + +bool ConanInstallStep::fromMap(const QVariantMap &map) +{ + m_relativeSubdir = map.value(INSTALL_STEP_CONANFILE_SUBDIR_KEY).toString(); + m_additionalArguments = map.value(INSTALL_STEP_ADDITIONAL_ARGUMENTS_KEY).toString(); + + return BuildStep::fromMap(map); +} + +/////////////////////////////// +// ConanInstallStepConfigWidget class +/////////////////////////////// +ConanInstallStepConfigWidget::ConanInstallStepConfigWidget(ConanInstallStep *installStep) + : ProjectExplorer::BuildStepConfigWidget(installStep) + , m_installStep(installStep) + , m_summaryText() + , m_relativeSubdir(nullptr) + , m_additionalArguments(nullptr) +{ + QFormLayout *fl = new QFormLayout(this); + fl->setMargin(0); + fl->setFieldGrowthPolicy(QFormLayout::ExpandingFieldsGrow); + setLayout(fl); + + m_relativeSubdir = new QLineEdit(this); + fl->addRow(tr("conanfile.txt subdirectory:"), m_relativeSubdir); + m_relativeSubdir->setText(m_installStep->relativeSubdir()); + + m_additionalArguments = new QLineEdit(this); + fl->addRow(tr("Additional arguments:"), m_additionalArguments); + m_additionalArguments->setText(Utils::QtcProcess::joinArgs(m_installStep->additionalArguments())); + + updateDetails(); + + connect(m_relativeSubdir, &QLineEdit::textChanged, + m_installStep, &ConanInstallStep::setRelativeSubdir); + connect(m_additionalArguments, &QLineEdit::textChanged, + m_installStep, &ConanInstallStep::setAdditionalArguments); + + connect(m_installStep, &ConanInstallStep::relativeSubdirChanged, + this, &ConanInstallStepConfigWidget::updateDetails); + connect(m_installStep, &ConanInstallStep::additionalArgumentsChanged, + this, &ConanInstallStepConfigWidget::updateDetails); + connect(installStep->buildConfiguration(), &BuildConfiguration::environmentChanged, + this, &ConanInstallStepConfigWidget::updateDetails); +} + +QString ConanInstallStepConfigWidget::displayName() const +{ + return tr("conan install", "ConanInstallStep::ConanInstallStepConfigWidget display name."); +} + +QString ConanInstallStepConfigWidget::summaryText() const +{ + return m_summaryText; +} + +void ConanInstallStepConfigWidget::updateDetails() +{ + BuildConfiguration *bc = m_installStep->buildConfiguration(); + if (!bc) + bc = m_installStep->target()->activeBuildConfiguration(); + QList tcList = ToolChainKitAspect::toolChains(m_installStep->target()->kit()); + + if (!tcList.isEmpty()) { + QString arguments = Utils::QtcProcess::joinArgs(m_installStep->arguments() + + m_installStep->additionalArguments()); + m_summaryText = "conan install: conan " + arguments; + setSummaryText(m_summaryText); + } else { + m_summaryText = "" + ToolChainKitAspect::msgNoToolChainInTarget() + ""; + } + + emit updateSummary(); +} + +} // namespace Internal +} // namespace ConanPackageManager diff --git a/src/plugins/conan/conaninstallstep.h b/src/plugins/conan/conaninstallstep.h new file mode 100644 index 00000000000..d6dad5201d9 --- /dev/null +++ b/src/plugins/conan/conaninstallstep.h @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** Copyright (C) 2018 Jochen Seemann +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include +#include + +QT_FORWARD_DECLARE_CLASS(QLineEdit) + +namespace ConanPackageManager { +namespace Internal { + +class AutotoolsProject; +class ConanInstallStep; +class ConanInstallStepFactory : public ProjectExplorer::BuildStepFactory +{ +public: + ConanInstallStepFactory(); +}; + +class ConanInstallStep : public ProjectExplorer::AbstractProcessStep +{ + Q_OBJECT + friend class ConanInstallStepFactory; + +public: + ConanInstallStep(ProjectExplorer::BuildStepList *bsl, Utils::Id id); + + bool init() override; + ProjectExplorer::BuildStepConfigWidget *createConfigWidget() override; + bool immutable() const; + QStringList arguments() const; + QString relativeSubdir() const; + QStringList additionalArguments() const; + QVariantMap toMap() const override; + + void setRelativeSubdir(const QString &subdir); + void setAdditionalArguments(const QString &list); + + void setupOutputFormatter(Utils::OutputFormatter *formatter) final; + +signals: + void relativeSubdirChanged(const QString &); + void additionalArgumentsChanged(const QString &); + +private: + bool fromMap(const QVariantMap &map) override; + + QString m_arguments; + QString m_relativeSubdir; + QString m_additionalArguments; +}; + +class ConanInstallStepConfigWidget : public ProjectExplorer::BuildStepConfigWidget +{ + Q_OBJECT + +public: + ConanInstallStepConfigWidget(ConanInstallStep *installStep); + + QString displayName() const; + QString summaryText() const; + +private: + void updateDetails(); + + ConanInstallStep *m_installStep; + QString m_summaryText; + QLineEdit *m_relativeSubdir; + QLineEdit *m_additionalArguments; +}; + +} // namespace Internal +} // namespace ConanPackageManager diff --git a/src/plugins/conan/conanplugin.cpp b/src/plugins/conan/conanplugin.cpp new file mode 100644 index 00000000000..bf88c803fc7 --- /dev/null +++ b/src/plugins/conan/conanplugin.cpp @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** Copyright (C) 2018 Jochen Seemann +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "conanplugin.h" +#include "conaninstallstep.h" + +#include +#include + +namespace ConanPackageManager { +namespace Internal { + +class ConanPluginRunData +{ +public: + ConanInstallStepFactory installStepFactory; +}; + +ConanPlugin::~ConanPlugin() +{ + delete m_runData; +} + +void ConanPlugin::extensionsInitialized() +{ } + +bool ConanPlugin::initialize(const QStringList &arguments, QString *errorString) +{ + Q_UNUSED(arguments) + Q_UNUSED(errorString) + + m_runData = new ConanPluginRunData; + + return true; +} + +} // namespace Internal +} // namespace ConanPackageManager diff --git a/src/plugins/conan/conanplugin.h b/src/plugins/conan/conanplugin.h new file mode 100644 index 00000000000..d77409ec972 --- /dev/null +++ b/src/plugins/conan/conanplugin.h @@ -0,0 +1,49 @@ +/**************************************************************************** +** +** Copyright (C) 2018 Jochen Seemann +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include + +namespace ConanPackageManager { +namespace Internal { + +class ConanPluginRunData; + +class ConanPlugin final : public ExtensionSystem::IPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "Conan.json") + + ~ConanPlugin() final; + + void extensionsInitialized() final; + bool initialize(const QStringList &arguments, QString *errorString) final; + + ConanPluginRunData *m_runData = nullptr; +}; + +} // namespace Internal +} // namespace ConanPackageManager diff --git a/src/plugins/plugins.pro b/src/plugins/plugins.pro index 12d87206ab3..abf6e510c08 100644 --- a/src/plugins/plugins.pro +++ b/src/plugins/plugins.pro @@ -66,7 +66,8 @@ SUBDIRS = \ webassembly \ mcusupport \ marketplace \ - incredibuild + incredibuild \ + conan qtHaveModule(serialport) { SUBDIRS += serialterminal diff --git a/src/plugins/plugins.qbs b/src/plugins/plugins.qbs index 5ef58f33ebf..e2310ee1ff5 100644 --- a/src/plugins/plugins.qbs +++ b/src/plugins/plugins.qbs @@ -23,6 +23,7 @@ Project { "cmakeprojectmanager/cmakeprojectmanager.qbs", "mesonprojectmanager/mesonprojectmanager.qbs", "compilationdatabaseprojectmanager/compilationdatabaseprojectmanager.qbs", + "conan/conan.qbs", "coreplugin/coreplugin.qbs", "coreplugin/images/logo/logo.qbs", "cpaster/cpaster.qbs", From c3833406cca6fa9f8b947e49d6549cac609cb611 Mon Sep 17 00:00:00 2001 From: hjk Date: Mon, 5 Oct 2020 12:15:37 +0200 Subject: [PATCH 03/10] iOS: Remove unnecessary check in IosBuildStep::init() A buildstep always belongs to a build configuration. Change-Id: Ia24e571fbaf47c97797661774e87d583bddb1d76 Reviewed-by: Eike Ziller --- src/plugins/ios/iosbuildstep.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/plugins/ios/iosbuildstep.cpp b/src/plugins/ios/iosbuildstep.cpp index c529bf37571..dc7c99cf8f7 100644 --- a/src/plugins/ios/iosbuildstep.cpp +++ b/src/plugins/ios/iosbuildstep.cpp @@ -170,13 +170,9 @@ bool IosBuildStep::init() if (!AbstractProcessStep::init()) return false; - BuildConfiguration *bc = buildConfiguration(); - ToolChain *tc = ToolChainKitAspect::cxxToolChain(kit()); - if (!tc) + if (!tc) { emit addTask(Task::compilerMissingTask()); - - if (!bc || !tc) { emitFaultyConfigurationMessage(); return false; } From 2a5c5d118baa35f36015dcb7c2d929f931ecc779 Mon Sep 17 00:00:00 2001 From: hjk Date: Mon, 5 Oct 2020 12:42:37 +0200 Subject: [PATCH 04/10] AutoTools: Build step code cosmetics Change-Id: I5281bfaaa54ade80bbf46cfd16f629a2d1c81a9b Reviewed-by: Christian Stenger --- .../autotoolsprojectmanager/autogenstep.cpp | 26 +++++++--------- .../autoreconfstep.cpp | 31 +++++++++---------- .../autotoolsprojectmanager/configurestep.cpp | 28 ++++++++--------- 3 files changed, 40 insertions(+), 45 deletions(-) diff --git a/src/plugins/autotoolsprojectmanager/autogenstep.cpp b/src/plugins/autotoolsprojectmanager/autogenstep.cpp index 38b2e511e74..58a57c84507 100644 --- a/src/plugins/autotoolsprojectmanager/autogenstep.cpp +++ b/src/plugins/autotoolsprojectmanager/autogenstep.cpp @@ -57,36 +57,34 @@ namespace Internal { * It is possible for the user to specify custom arguments. */ -class AutogenStep : public AbstractProcessStep +class AutogenStep final : public AbstractProcessStep { Q_DECLARE_TR_FUNCTIONS(AutotoolsProjectManager::Internal::AutogenStep) public: - AutogenStep(BuildStepList *bsl, Utils::Id id); + AutogenStep(BuildStepList *bsl, Id id); private: - void doRun() override; + void doRun() final; - StringAspect *m_additionalArgumentsAspect = nullptr; bool m_runAutogen = false; }; -AutogenStep::AutogenStep(BuildStepList *bsl, Utils::Id id) : AbstractProcessStep(bsl, id) +AutogenStep::AutogenStep(BuildStepList *bsl, Id id) : AbstractProcessStep(bsl, id) { - m_additionalArgumentsAspect = addAspect(); - m_additionalArgumentsAspect->setSettingsKey( - "AutotoolsProjectManager.AutogenStep.AdditionalArguments"); - m_additionalArgumentsAspect->setLabelText(tr("Arguments:")); - m_additionalArgumentsAspect->setDisplayStyle(StringAspect::LineEditDisplay); - m_additionalArgumentsAspect->setHistoryCompleter("AutotoolsPM.History.AutogenStepArgs"); + auto arguments = addAspect(); + arguments->setSettingsKey("AutotoolsProjectManager.AutogenStep.AdditionalArguments"); + arguments->setLabelText(tr("Arguments:")); + arguments->setDisplayStyle(StringAspect::LineEditDisplay); + arguments->setHistoryCompleter("AutotoolsPM.History.AutogenStepArgs"); - connect(m_additionalArgumentsAspect, &BaseAspect::changed, this, [this] { + connect(arguments, &BaseAspect::changed, this, [this] { m_runAutogen = true; }); - setCommandLineProvider([this] { + setCommandLineProvider([arguments] { return CommandLine(FilePath::fromString("./autogen.sh"), - m_additionalArgumentsAspect->value(), + arguments->value(), CommandLine::Raw); }); diff --git a/src/plugins/autotoolsprojectmanager/autoreconfstep.cpp b/src/plugins/autotoolsprojectmanager/autoreconfstep.cpp index 030922920af..c1a92298dae 100644 --- a/src/plugins/autotoolsprojectmanager/autoreconfstep.cpp +++ b/src/plugins/autotoolsprojectmanager/autoreconfstep.cpp @@ -55,38 +55,37 @@ namespace Internal { * It is possible for the user to specify custom arguments. */ -class AutoreconfStep : public AbstractProcessStep +class AutoreconfStep final : public AbstractProcessStep { Q_DECLARE_TR_FUNCTIONS(AutotoolsProjectManager::Internal::AutoreconfStep) public: - AutoreconfStep(BuildStepList *bsl, Utils::Id id); + AutoreconfStep(BuildStepList *bsl, Id id); void doRun() override; private: - StringAspect *m_additionalArgumentsAspect = nullptr; bool m_runAutoreconf = false; }; -AutoreconfStep::AutoreconfStep(BuildStepList *bsl, Utils::Id id) +AutoreconfStep::AutoreconfStep(BuildStepList *bsl, Id id) : AbstractProcessStep(bsl, id) { - m_additionalArgumentsAspect = addAspect(); - m_additionalArgumentsAspect->setSettingsKey("AutotoolsProjectManager.AutoreconfStep.AdditionalArguments"); - m_additionalArgumentsAspect->setLabelText(tr("Arguments:")); - m_additionalArgumentsAspect->setValue("--force --install"); - m_additionalArgumentsAspect->setDisplayStyle(StringAspect::LineEditDisplay); - m_additionalArgumentsAspect->setHistoryCompleter("AutotoolsPM.History.AutoreconfStepArgs"); + auto arguments = addAspect(); + arguments->setSettingsKey("AutotoolsProjectManager.AutoreconfStep.AdditionalArguments"); + arguments->setLabelText(tr("Arguments:")); + arguments->setValue("--force --install"); + arguments->setDisplayStyle(StringAspect::LineEditDisplay); + arguments->setHistoryCompleter("AutotoolsPM.History.AutoreconfStepArgs"); - connect(m_additionalArgumentsAspect, &BaseAspect::changed, this, [this] { + connect(arguments, &BaseAspect::changed, this, [this] { m_runAutoreconf = true; }); - setCommandLineProvider([this] { - return Utils::CommandLine(Utils::FilePath::fromString("autoreconf"), - m_additionalArgumentsAspect->value(), - Utils::CommandLine::Raw); + setCommandLineProvider([arguments] { + return CommandLine(FilePath::fromString("autoreconf"), + arguments->value(), + CommandLine::Raw); }); setWorkingDirectoryProvider([this] { return project()->projectDirectory(); }); @@ -107,7 +106,7 @@ void AutoreconfStep::doRun() m_runAutoreconf = true; if (!m_runAutoreconf) { - emit addOutput(tr("Configuration unchanged, skipping autoreconf step."), BuildStep::OutputFormat::NormalMessage); + emit addOutput(tr("Configuration unchanged, skipping autoreconf step."), OutputFormat::NormalMessage); emit finished(true); return; } diff --git a/src/plugins/autotoolsprojectmanager/configurestep.cpp b/src/plugins/autotoolsprojectmanager/configurestep.cpp index dea7c90b1eb..cd8676d0b85 100644 --- a/src/plugins/autotoolsprojectmanager/configurestep.cpp +++ b/src/plugins/autotoolsprojectmanager/configurestep.cpp @@ -74,43 +74,41 @@ static QString projectDirRelativeToBuildDir(BuildConfiguration *bc) // * represented by an instance of the class MakeStepConfigWidget. // */ -class ConfigureStep : public ProjectExplorer::AbstractProcessStep +class ConfigureStep final : public AbstractProcessStep { Q_DECLARE_TR_FUNCTIONS(AutotoolsProjectManager::Internal::ConfigureStep) public: - ConfigureStep(BuildStepList *bsl, Utils::Id id); + ConfigureStep(BuildStepList *bsl, Id id); void setAdditionalArguments(const QString &list); private: - void doRun() override; + void doRun() final; - StringAspect *m_additionalArgumentsAspect = nullptr; bool m_runConfigure = false; }; -ConfigureStep::ConfigureStep(BuildStepList *bsl, Utils::Id id) +ConfigureStep::ConfigureStep(BuildStepList *bsl, Id id) : AbstractProcessStep(bsl, id) { - m_additionalArgumentsAspect = addAspect(); - m_additionalArgumentsAspect->setDisplayStyle(StringAspect::LineEditDisplay); - m_additionalArgumentsAspect->setSettingsKey( - "AutotoolsProjectManager.ConfigureStep.AdditionalArguments"); - m_additionalArgumentsAspect->setLabelText(tr("Arguments:")); - m_additionalArgumentsAspect->setHistoryCompleter("AutotoolsPM.History.ConfigureArgs"); + auto arguments = addAspect(); + arguments->setDisplayStyle(StringAspect::LineEditDisplay); + arguments->setSettingsKey("AutotoolsProjectManager.ConfigureStep.AdditionalArguments"); + arguments->setLabelText(tr("Arguments:")); + arguments->setHistoryCompleter("AutotoolsPM.History.ConfigureArgs"); - connect(m_additionalArgumentsAspect, &BaseAspect::changed, this, [this] { + connect(arguments, &BaseAspect::changed, this, [this] { m_runConfigure = true; }); setWorkingDirectoryProvider([this] { return project()->projectDirectory(); }); - setCommandLineProvider([this] { + setCommandLineProvider([this, arguments] { BuildConfiguration *bc = buildConfiguration(); return CommandLine({FilePath::fromString(projectDirRelativeToBuildDir(bc) + "configure"), - m_additionalArgumentsAspect->value(), + arguments->value(), CommandLine::Raw}); }); @@ -135,7 +133,7 @@ void ConfigureStep::doRun() } if (!m_runConfigure) { - emit addOutput(tr("Configuration unchanged, skipping configure step."), BuildStep::OutputFormat::NormalMessage); + emit addOutput(tr("Configuration unchanged, skipping configure step."), OutputFormat::NormalMessage); emit finished(true); return; } From 82d64ea49fb93485bd8128e62e060911fa9dd8a4 Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Mon, 5 Oct 2020 14:50:46 +0200 Subject: [PATCH 05/10] Doc: Modify the terminology in the "Shapes" topic Change-Id: Ibabca1fa03cc3c063ae066d0c8c8e79a1a3b25b0 Reviewed-by: Brook Cronin Reviewed-by: Thomas Hartmann --- .../src/qtquick/library/qtquick-shapes.qdoc | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/doc/qtcreator/src/qtquick/library/qtquick-shapes.qdoc b/doc/qtcreator/src/qtquick/library/qtquick-shapes.qdoc index ed178387d8d..786a9c85f7f 100644 --- a/doc/qtcreator/src/qtquick/library/qtquick-shapes.qdoc +++ b/doc/qtcreator/src/qtquick/library/qtquick-shapes.qdoc @@ -39,7 +39,7 @@ However, you can use some of the components in \uicontrol Library to draw basic shapes, such as rectangles. In addition, \QDS comes with a set of more powerful and flexible graphical primitives, that allow creating more - complex shapes, such as lines, triangles, arcs, and pies in + complex shapes, such as borders, triangles, arcs, and pies in \uicontrol {Form Editor}. \image studio-shapes.png "Shapes in Form Editor" @@ -98,11 +98,15 @@ \if defined(qtdesignstudio) \section2 Studio Rectangle - If you want to draw asymmetric shapes or use a dashed border, for example, - select the Rectangle type in the \uicontrol {Studio Components} tab of - \uicontrol Library instead of the basic rectangle type. By setting the - values of properties in the \uicontrol {Corner Radiuses} and - \uicontrol {Corner Bevel} groups, you can create shapes with cut corners. + If you want to modify each corner of the rectangle independently + or use a dashed border, select the Rectangle type in the + \uicontrol {Studio Components} tab of \uicontrol Library instead + of the basic rectangle type. + + By setting the values of properties in the \uicontrol {Corner Radiuses} + group, you can draw each corner independently. By using radius values + in combination with the values in the \uicontrol {Corner Bevel} group, + you can create shapes with cut corners. \image studio-shapes-rectangle.png "A studio rectangle with cut corners" From ee5feb4939007a1114c420dcac808b4398c19855 Mon Sep 17 00:00:00 2001 From: hjk Date: Fri, 2 Oct 2020 13:45:54 +0200 Subject: [PATCH 06/10] Conan: Use Utils::Aspects in build step implementation Task-number: QTCREATORBUG-21785 Change-Id: I5b2dbcc16a2504efe9fdc9e31fa2ef14bba7c33c Reviewed-by: Kai Koehne --- src/plugins/conan/conaninstallstep.cpp | 251 +++++++------------------ src/plugins/conan/conaninstallstep.h | 61 +----- 2 files changed, 67 insertions(+), 245 deletions(-) diff --git a/src/plugins/conan/conaninstallstep.cpp b/src/plugins/conan/conaninstallstep.cpp index 53770859e9f..d651a2cb877 100644 --- a/src/plugins/conan/conaninstallstep.cpp +++ b/src/plugins/conan/conaninstallstep.cpp @@ -25,68 +25,90 @@ #include "conaninstallstep.h" -#include +#include #include -#include -#include -#include +#include #include #include #include -#include #include -#include -#include -#include - -#include -#include -#include +#include +#include +#include +#include using namespace ProjectExplorer; -using namespace ProjectExplorer::Constants; using namespace Utils; namespace ConanPackageManager { namespace Internal { -const char INSTALL_STEP_ID[] = "ConanPackageManager.InstallStep"; -const char INSTALL_STEP_CONANFILE_SUBDIR_KEY[] = "ConanPackageManager.InstallStep.ConanfileSubdir"; -const char INSTALL_STEP_ADDITIONAL_ARGUMENTS_KEY[] = "ConanPackageManager.InstallStep.AdditionalArguments"; +// ConanInstallStep -ConanInstallStepFactory::ConanInstallStepFactory() +class ConanInstallStep final : public AbstractProcessStep { - registerStep(INSTALL_STEP_ID); - setDisplayName(ConanInstallStep::tr("conan install", "Install packages specified in Conanfile.txt")); -} + Q_DECLARE_TR_FUNCTIONS(ConanPackageManager::Internal::ConanInstallStep) -ConanInstallStep::ConanInstallStep(BuildStepList *bsl, Utils::Id id) : AbstractProcessStep(bsl, id) +public: + ConanInstallStep(BuildStepList *bsl, Id id); + +private: + bool init() final; + void setupOutputFormatter(OutputFormatter *formatter) final; +}; + +ConanInstallStep::ConanInstallStep(BuildStepList *bsl, Id id) + : AbstractProcessStep(bsl, id) { - setDefaultDisplayName(tr("conan install")); + setUseEnglishOutput(); + setDisplayName(ConanInstallStep::tr("Conan install")); + + auto conanFile = addAspect(); + conanFile->setSettingsKey("ConanPackageManager.InstallStep.ConanFile"); + conanFile->setFilePath(project()->projectDirectory() / "conanfile.txt"); + conanFile->setLabelText(tr("Conan file:")); + conanFile->setToolTip(tr("Enter location of conanfile.txt or conanfile.py")); + conanFile->setDisplayStyle(StringAspect::PathChooserDisplay); + conanFile->setExpectedKind(PathChooser::File); + + auto additionalArguments = addAspect(); + additionalArguments->setSettingsKey("ConanPackageManager.InstallStep.AdditionalArguments"); + additionalArguments->setLabelText(tr("Additional arguments:")); + additionalArguments->setDisplayStyle(StringAspect::LineEditDisplay); + + setCommandLineProvider([this, conanFile, additionalArguments] { + BuildConfiguration::BuildType bt = buildConfiguration()->buildType(); + const QString buildType = bt == BuildConfiguration::Release ? QString("Release") + : QString("Debug"); + CommandLine cmd("conan"); + cmd.addArgs({"install", "-s", "build_type=" + buildType, conanFile->value()}); + cmd.addArgs(additionalArguments->value(), CommandLine::Raw); + return cmd; + }); + + setSummaryUpdater([this]() -> QString { + QList tcList = ToolChainKitAspect::toolChains(target()->kit()); + if (tcList.isEmpty()) + return "" + ToolChainKitAspect::msgNoToolChainInTarget() + ""; + ProcessParameters param; + setupProcessParameters(¶m); + return param.summary(displayName()); + }); } bool ConanInstallStep::init() { - BuildConfiguration *bc = buildConfiguration(); - QTC_ASSERT(bc, return false); + if (!AbstractProcessStep::init()) + return false; - QList tcList = ToolChainKitAspect::toolChains(target()->kit()); - if (tcList.isEmpty()) + const QList tcList = ToolChainKitAspect::toolChains(target()->kit()); + if (tcList.isEmpty()) { emit addTask(Task::compilerMissingTask()); - - if (tcList.isEmpty() || !bc) { emitFaultyConfigurationMessage(); return false; } - ProcessParameters *pp = processParameters(); - Utils::Environment env = bc->environment(); - Utils::Environment::setupEnglishOutput(&env); - pp->setEnvironment(env); - pp->setWorkingDirectory(bc->buildDirectory()); - pp->setCommandLine(Utils::CommandLine("conan", arguments())); - - return AbstractProcessStep::init(); + return true; } void ConanInstallStep::setupOutputFormatter(OutputFormatter *formatter) @@ -97,156 +119,13 @@ void ConanInstallStep::setupOutputFormatter(OutputFormatter *formatter) AbstractProcessStep::setupOutputFormatter(formatter); } -BuildStepConfigWidget *ConanInstallStep::createConfigWidget() +// ConanInstallStepFactory + +ConanInstallStepFactory::ConanInstallStepFactory() { - return new ConanInstallStepConfigWidget(this); + registerStep("ConanPackageManager.InstallStep"); + setDisplayName(ConanInstallStep::tr("Run conan install")); } -bool ConanInstallStep::immutable() const -{ - return false; -} - -QStringList ConanInstallStep::arguments() const -{ - BuildConfiguration *bc = buildConfiguration(); - if (!bc) - bc = target()->activeBuildConfiguration(); - - if (!bc) - return {}; - - const Utils::FilePath conanFileDir = relativeSubdir().isEmpty() - ? bc->buildDirectory() - : bc->buildDirectory().pathAppended(relativeSubdir()); - - const QString buildType = bc->buildType() == BuildConfiguration::Release ? QString("Release") - : QString("Debug"); - const QString relativePath - = bc->project()->projectDirectory().relativeChildPath(conanFileDir).toString(); - QStringList installArguments; - installArguments << "install"; - if (!relativePath.isEmpty()) - installArguments << relativePath; - installArguments << "-s"; - installArguments << "build_type=" + buildType; - installArguments << conanFileDir.toString(); - installArguments << additionalArguments(); - return installArguments; -} - -QString ConanInstallStep::relativeSubdir() const -{ - return m_relativeSubdir; -} - -QStringList ConanInstallStep::additionalArguments() const -{ - return Utils::QtcProcess::splitArgs(m_additionalArguments); -} - -void ConanInstallStep::setRelativeSubdir(const QString &subdir) -{ - if (subdir == m_relativeSubdir) - return; - - m_relativeSubdir = subdir; - emit relativeSubdirChanged(subdir); -} - -void ConanInstallStep::setAdditionalArguments(const QString &list) -{ - if (list == m_additionalArguments) - return; - - m_additionalArguments = list; - - emit additionalArgumentsChanged(list); -} - -QVariantMap ConanInstallStep::toMap() const -{ - QVariantMap map = AbstractProcessStep::toMap(); - - map.insert(INSTALL_STEP_CONANFILE_SUBDIR_KEY, m_relativeSubdir); - map.insert(INSTALL_STEP_ADDITIONAL_ARGUMENTS_KEY, m_additionalArguments); - return map; -} - -bool ConanInstallStep::fromMap(const QVariantMap &map) -{ - m_relativeSubdir = map.value(INSTALL_STEP_CONANFILE_SUBDIR_KEY).toString(); - m_additionalArguments = map.value(INSTALL_STEP_ADDITIONAL_ARGUMENTS_KEY).toString(); - - return BuildStep::fromMap(map); -} - -/////////////////////////////// -// ConanInstallStepConfigWidget class -/////////////////////////////// -ConanInstallStepConfigWidget::ConanInstallStepConfigWidget(ConanInstallStep *installStep) - : ProjectExplorer::BuildStepConfigWidget(installStep) - , m_installStep(installStep) - , m_summaryText() - , m_relativeSubdir(nullptr) - , m_additionalArguments(nullptr) -{ - QFormLayout *fl = new QFormLayout(this); - fl->setMargin(0); - fl->setFieldGrowthPolicy(QFormLayout::ExpandingFieldsGrow); - setLayout(fl); - - m_relativeSubdir = new QLineEdit(this); - fl->addRow(tr("conanfile.txt subdirectory:"), m_relativeSubdir); - m_relativeSubdir->setText(m_installStep->relativeSubdir()); - - m_additionalArguments = new QLineEdit(this); - fl->addRow(tr("Additional arguments:"), m_additionalArguments); - m_additionalArguments->setText(Utils::QtcProcess::joinArgs(m_installStep->additionalArguments())); - - updateDetails(); - - connect(m_relativeSubdir, &QLineEdit::textChanged, - m_installStep, &ConanInstallStep::setRelativeSubdir); - connect(m_additionalArguments, &QLineEdit::textChanged, - m_installStep, &ConanInstallStep::setAdditionalArguments); - - connect(m_installStep, &ConanInstallStep::relativeSubdirChanged, - this, &ConanInstallStepConfigWidget::updateDetails); - connect(m_installStep, &ConanInstallStep::additionalArgumentsChanged, - this, &ConanInstallStepConfigWidget::updateDetails); - connect(installStep->buildConfiguration(), &BuildConfiguration::environmentChanged, - this, &ConanInstallStepConfigWidget::updateDetails); -} - -QString ConanInstallStepConfigWidget::displayName() const -{ - return tr("conan install", "ConanInstallStep::ConanInstallStepConfigWidget display name."); -} - -QString ConanInstallStepConfigWidget::summaryText() const -{ - return m_summaryText; -} - -void ConanInstallStepConfigWidget::updateDetails() -{ - BuildConfiguration *bc = m_installStep->buildConfiguration(); - if (!bc) - bc = m_installStep->target()->activeBuildConfiguration(); - QList tcList = ToolChainKitAspect::toolChains(m_installStep->target()->kit()); - - if (!tcList.isEmpty()) { - QString arguments = Utils::QtcProcess::joinArgs(m_installStep->arguments() - + m_installStep->additionalArguments()); - m_summaryText = "conan install: conan " + arguments; - setSummaryText(m_summaryText); - } else { - m_summaryText = "" + ToolChainKitAspect::msgNoToolChainInTarget() + ""; - } - - emit updateSummary(); -} - -} // namespace Internal -} // namespace ConanPackageManager +} // Internal +} // ConanPackageManager diff --git a/src/plugins/conan/conaninstallstep.h b/src/plugins/conan/conaninstallstep.h index d6dad5201d9..f4deb02dd4b 100644 --- a/src/plugins/conan/conaninstallstep.h +++ b/src/plugins/conan/conaninstallstep.h @@ -25,73 +25,16 @@ #pragma once -#include -#include - -QT_FORWARD_DECLARE_CLASS(QLineEdit) +#include namespace ConanPackageManager { namespace Internal { -class AutotoolsProject; -class ConanInstallStep; -class ConanInstallStepFactory : public ProjectExplorer::BuildStepFactory +class ConanInstallStepFactory final : public ProjectExplorer::BuildStepFactory { public: ConanInstallStepFactory(); }; -class ConanInstallStep : public ProjectExplorer::AbstractProcessStep -{ - Q_OBJECT - friend class ConanInstallStepFactory; - -public: - ConanInstallStep(ProjectExplorer::BuildStepList *bsl, Utils::Id id); - - bool init() override; - ProjectExplorer::BuildStepConfigWidget *createConfigWidget() override; - bool immutable() const; - QStringList arguments() const; - QString relativeSubdir() const; - QStringList additionalArguments() const; - QVariantMap toMap() const override; - - void setRelativeSubdir(const QString &subdir); - void setAdditionalArguments(const QString &list); - - void setupOutputFormatter(Utils::OutputFormatter *formatter) final; - -signals: - void relativeSubdirChanged(const QString &); - void additionalArgumentsChanged(const QString &); - -private: - bool fromMap(const QVariantMap &map) override; - - QString m_arguments; - QString m_relativeSubdir; - QString m_additionalArguments; -}; - -class ConanInstallStepConfigWidget : public ProjectExplorer::BuildStepConfigWidget -{ - Q_OBJECT - -public: - ConanInstallStepConfigWidget(ConanInstallStep *installStep); - - QString displayName() const; - QString summaryText() const; - -private: - void updateDetails(); - - ConanInstallStep *m_installStep; - QString m_summaryText; - QLineEdit *m_relativeSubdir; - QLineEdit *m_additionalArguments; -}; - } // namespace Internal } // namespace ConanPackageManager From 33c3fe2c672b1418e2c0d09a3ad5a081f5bd1d0d Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Mon, 5 Oct 2020 15:01:01 +0200 Subject: [PATCH 07/10] Designer: Fix test Amends 142c47bdc2eb4. Change-Id: I30ff356687d4daef93d35744fd8c108eafed0c68 Reviewed-by: David Schulz --- src/plugins/designer/gotoslot_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/designer/gotoslot_test.cpp b/src/plugins/designer/gotoslot_test.cpp index 8e06f6e2d05..64d5bc4295a 100644 --- a/src/plugins/designer/gotoslot_test.cpp +++ b/src/plugins/designer/gotoslot_test.cpp @@ -195,7 +195,7 @@ public: const auto cppDocumentParser = BuiltinEditorDocumentParser::get(cppFile); QVERIFY(cppDocumentParser); const Document::Ptr cppDocument = cppDocumentParser->document(); - QCOMPARE(cppDocument->editorRevision(), 2); + QVERIFY(cppDocument->editorRevision() >= 2); QVERIFY(checkDiagsnosticMessages(cppDocument)); const auto hDocumentParser = BuiltinEditorDocumentParser::get(hFile); From f08c3d150af86a4c0760054e5b6cdbff023f8634 Mon Sep 17 00:00:00 2001 From: hjk Date: Wed, 12 Aug 2020 00:18:00 +0200 Subject: [PATCH 08/10] Debugger: Fix parsing of octal-encoded gdb escapes Fixes: QTCREATORBUG-24462 Change-Id: I89153a04eeef6a2e20fefef45e0efa3712ec0997 Reviewed-by: Christian Stenger --- src/plugins/debugger/debuggerprotocol.cpp | 181 +++++++++++----------- tests/auto/debugger/CMakeLists.txt | 9 ++ tests/auto/debugger/debugger.pro | 1 + tests/auto/debugger/debugger.qbs | 1 + tests/auto/debugger/protocol.pro | 46 ++++++ tests/auto/debugger/protocol.qbs | 17 ++ tests/auto/debugger/tst_protocol.cpp | 92 +++++++++++ 7 files changed, 260 insertions(+), 87 deletions(-) create mode 100644 tests/auto/debugger/protocol.pro create mode 100644 tests/auto/debugger/protocol.qbs create mode 100644 tests/auto/debugger/tst_protocol.cpp diff --git a/src/plugins/debugger/debuggerprotocol.cpp b/src/plugins/debugger/debuggerprotocol.cpp index ccd834636c6..b62931705f7 100644 --- a/src/plugins/debugger/debuggerprotocol.cpp +++ b/src/plugins/debugger/debuggerprotocol.cpp @@ -89,104 +89,111 @@ void GdbMi::parseResultOrValue(const QChar *&from, const QChar *to) } } +// Reads one \ooo entity. +static bool parseOctalEscapedHelper(const QChar *&from, const QChar *to, QByteArray &buffer) +{ + if (to - from < 4) + return false; + if (*from != '\\') + return false; + + const char c1 = from[1].unicode(); + const char c2 = from[2].unicode(); + const char c3 = from[3].unicode(); + if (!isdigit(c1) || !isdigit(c2) || !isdigit(c3)) + return false; + + buffer += char((c1 - '0') * 64 + (c2 - '0') * 8 + (c3 - '0')); + from += 4; + return true; +} + +static bool parseHexEscapedHelper(const QChar *&from, const QChar *to, QByteArray &buffer) +{ + if (to - from < 4) + return false; + if (from[0]!= '\\') + return false; + if (from[1] != 'x') + return false; + + const char c1 = from[2].unicode(); + const char c2 = from[3].unicode(); + if (!isxdigit(c1) || !isxdigit(c2)) + return false; + + buffer += char(16 * fromhex(c1) + fromhex(c2)); + from += 4; + return true; +} + +static void parseSimpleEscape(const QChar *&from, const QChar *to, QString &result) +{ + if (from == to) { + qDebug() << "MI Parse Error, unterminated backslash escape"; + return; + } + + QChar c = *from++; + switch (c.unicode()) { + case 'a': result += '\a'; break; + case 'b': result += '\b'; break; + case 'f': result += '\f'; break; + case 'n': result += '\n'; break; + case 'r': result += '\r'; break; + case 't': result += '\t'; break; + case 'v': result += '\v'; break; + case '"': result += '"'; break; + case '\'': result += '\''; break; + case '\\': result += '\\'; break; + default: + qDebug() << "MI Parse Error, unrecognized backslash escape"; + } +} + +// Reads subsequent \123 or \x12 entities and converts to Utf8, +// *or* one escaped char, *or* one unescaped char. +static void parseCharOrEscape(const QChar *&from, const QChar *to, QString &result) +{ + QByteArray buffer; + while (parseOctalEscapedHelper(from, to, buffer)) + ; + while (parseHexEscapedHelper(from, to, buffer)) + ; + + if (!buffer.isEmpty()) + result.append(QString::fromUtf8(buffer)); + else if (*from == '\\') + parseSimpleEscape(++from, to, result); + else + result += *from++; +} + QString GdbMi::parseCString(const QChar *&from, const QChar *to) { - QString result; + if (to == from) + return QString(); + //qDebug() << "parseCString: " << QString(from, to - from); if (*from != '"') { qDebug() << "MI Parse Error, double quote expected"; ++from; // So we don't hang return QString(); } - const QChar *ptr = from; - ++ptr; - while (ptr < to) { - if (*ptr == '"') { - ++ptr; - result = QString(from + 1, ptr - from - 2); - break; - } - if (*ptr == '\\') { - ++ptr; - if (ptr == to) { - qDebug() << "MI Parse Error, unterminated backslash escape"; - from = ptr; // So we don't hang - return QString(); - } - } - ++ptr; - } - from = ptr; - int idx = result.indexOf('\\'); - if (idx >= 0) { - QChar *dst = result.data() + idx; - const QChar *src = dst + 1, *end = result.data() + result.length(); - do { - QChar c = *src++; - switch (c.unicode()) { - case 'a': *dst++ = '\a'; break; - case 'b': *dst++ = '\b'; break; - case 'f': *dst++ = '\f'; break; - case 'n': *dst++ = '\n'; break; - case 'r': *dst++ = '\r'; break; - case 't': *dst++ = '\t'; break; - case 'v': *dst++ = '\v'; break; - case '"': *dst++ = '"'; break; - case '\\': *dst++ = '\\'; break; - case 'x': { - c = *src++; - int chars = 0; - uchar prod = 0; - while (true) { - uchar val = fromhex(c.unicode()); - if (val == UCHAR_MAX) - break; - prod = prod * 16 + val; - if (++chars == 3 || src == end) - break; - c = *src++; - } - if (!chars) { - qDebug() << "MI Parse Error, unrecognized hex escape"; - return QString(); - } - *dst++ = prod; - break; - } - default: - { - int chars = 0; - uchar prod = 0; - forever { - if (c < '0' || c > '7') { - --src; - break; - } - prod = prod * 8 + c.unicode() - '0'; - if (++chars == 3 || src == end) - break; - c = *src++; - } - if (!chars) { - qDebug() << "MI Parse Error, unrecognized backslash escape"; - return QString(); - } - *dst++ = prod; - } - } - while (src != end) { - QChar c = *src++; - if (c == '\\') - break; - *dst++ = c; - } - } while (src != end); - *dst = 0; - result.truncate(dst - result.data()); + ++from; // Skip initial quote. + QString result; + result.reserve(to - from); + while (from < to) { + if (*from == '"') { + ++from; + return result; + } + parseCharOrEscape(from, to, result); } - return result; + qDebug() << "MI Parse Error, unfinished string"; + return QString(); } void GdbMi::parseValue(const QChar *&from, const QChar *to) diff --git a/tests/auto/debugger/CMakeLists.txt b/tests/auto/debugger/CMakeLists.txt index 66900623c34..71f48e399c1 100644 --- a/tests/auto/debugger/CMakeLists.txt +++ b/tests/auto/debugger/CMakeLists.txt @@ -32,6 +32,15 @@ add_qtc_test(tst_debugger_gdb "${DEBUGGERDIR}/debuggerprotocol.cpp" "${DEBUGGERDIR}/debuggerprotocol.h" ) +add_qtc_test(tst_debugger_protocol + DEPENDS Qt5::Network Utils + INCLUDES + "${DEBUGGERDIR}" + SOURCES + "${DEBUGGERDIR}/debuggerprotocol.cpp" "${DEBUGGERDIR}/debuggerprotocol.h" + tst_protocol.cpp +) + add_qtc_test(tst_debugger_offsets DEPENDS Qt5::CorePrivate INCLUDES "${DEBUGGERDIR}" diff --git a/tests/auto/debugger/debugger.pro b/tests/auto/debugger/debugger.pro index 284db38b0c8..6d24b5f7999 100644 --- a/tests/auto/debugger/debugger.pro +++ b/tests/auto/debugger/debugger.pro @@ -12,3 +12,4 @@ SUBDIRS += simplifytypes.pro SUBDIRS += dumpers.pro SUBDIRS += disassembler.pro SUBDIRS += offsets.pro +SUBDIRS += protocol.pro diff --git a/tests/auto/debugger/debugger.qbs b/tests/auto/debugger/debugger.qbs index 456c604b261..e4ae1051023 100644 --- a/tests/auto/debugger/debugger.qbs +++ b/tests/auto/debugger/debugger.qbs @@ -7,6 +7,7 @@ Project { "disassembler.qbs", "dumpers.qbs", "gdb.qbs", + "protocol.qbs", "offsets.qbs", "simplifytypes.qbs", ] diff --git a/tests/auto/debugger/protocol.pro b/tests/auto/debugger/protocol.pro new file mode 100644 index 00000000000..1008ba3d930 --- /dev/null +++ b/tests/auto/debugger/protocol.pro @@ -0,0 +1,46 @@ +QT = core network + +msvc: QTC_LIB_DEPENDS += utils +include(../qttest.pri) + +DEBUGGERDIR = $$IDE_SOURCE_TREE/src/plugins/debugger +UTILSDIR = $$IDE_SOURCE_TREE/src/libs/utils + +INCLUDEPATH += $$DEBUGGERDIR + +SOURCES += \ + tst_protocol.cpp \ + $$DEBUGGERDIR/debuggerprotocol.cpp + +HEADERS += \ + $$DEBUGGERDIR/debuggerprotocol.h + +!msvc { + SOURCES += \ + $$UTILSDIR/environment.cpp \ + $$UTILSDIR/fileutils.cpp \ + $$UTILSDIR/hostosinfo.cpp \ + $$UTILSDIR/namevaluedictionary.cpp \ + $$UTILSDIR/namevalueitem.cpp \ + $$UTILSDIR/qtcassert.cpp \ + $$UTILSDIR/qtcprocess.cpp \ + $$UTILSDIR/processhandle.cpp \ + $$UTILSDIR/savefile.cpp \ + + HEADERS += \ + $$UTILSDIR/environment.h \ + $$UTILSDIR/fileutils.h \ + $$UTILSDIR/hostosinfo.h \ + $$UTILSDIR/namevaluedictionary.h \ + $$UTILSDIR/namevalueitem.h \ + $$UTILSDIR/qtcassert.h \ + $$UTILSDIR/qtcprocess.h \ + $$UTILSDIR/processhandle.h \ + $$UTILSDIR/savefile.h \ + + macos: { + HEADERS += $$UTILSDIR/fileutils_mac.h + OBJECTIVE_SOURCES += $$UTILSDIR/fileutils_mac.mm + LIBS += -framework Foundation + } +} diff --git a/tests/auto/debugger/protocol.qbs b/tests/auto/debugger/protocol.qbs new file mode 100644 index 00000000000..ca1b0d8bece --- /dev/null +++ b/tests/auto/debugger/protocol.qbs @@ -0,0 +1,17 @@ +import qbs + +QtcAutotest { + name: "debugger protocol autotest" + Depends { name: "Utils" } + Depends { name: "Qt.network" } // For QHostAddress + Group { + name: "Sources from Debugger plugin" + prefix: project.debuggerDir + files: "debuggerprotocol.cpp" + } + Group { + name: "Test sources" + files: "tst_protocol.cpp" + } + cpp.includePaths: base.concat([project.debuggerDir]) +} diff --git a/tests/auto/debugger/tst_protocol.cpp b/tests/auto/debugger/tst_protocol.cpp new file mode 100644 index 00000000000..6d6f1190537 --- /dev/null +++ b/tests/auto/debugger/tst_protocol.cpp @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include + +#include + +//TESTED_COMPONENT=src/plugins/debugger + +class tst_protocol : public QObject +{ + Q_OBJECT + +public: + tst_protocol() {} + +private slots: + void parseCString(); + void parseCString_data(); +}; + +void tst_protocol::parseCString() +{ + QFETCH(QString, input); + QFETCH(QString, expected); + + const QChar *from = input.begin(); + const QChar *to = input.end(); + QString parsed = Debugger::Internal::GdbMi::parseCString(from, to); + + QCOMPARE(parsed, expected); +} + +void tst_protocol::parseCString_data() +{ + QTest::addColumn("input"); + QTest::addColumn("expected"); + + QTest::newRow("empty") + << "" + << ""; + + QTest::newRow("unquoted") + << "irgendwas" + << ""; + + QTest::newRow("plain") + << R"("plain")" + << "plain"; + + // This is expected to throw several warnings + // "MI Parse Error, unrecognized backslash escape" + QChar escapes[] = {'\a', '\b', '\f', '\n', '\r', '\t', '\v', '"', '\'', '\\'}; + QTest::newRow("escaped") + << R"("\a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\y\z\"\'\\")" + << QString(escapes, sizeof(escapes)/sizeof(escapes[0])); + + QTest::newRow("octal") + << R"("abc\303\244\303\251def\303\261")" + << R"(abcäédefñ)"; + + QTest::newRow("hex") + << R"("abc\xc3\xa4\xc3\xa9def\xc3\xb1")" + << R"(abcäédefñ)"; +} + +QTEST_APPLESS_MAIN(tst_protocol); + +#include "tst_protocol.moc" + From 90c757d9ccb70939a677e2ea91f4b11f1cab54aa Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Mon, 5 Oct 2020 15:45:47 +0200 Subject: [PATCH 09/10] ProjectExplorer: Make build and run widget width persistent ... by storing the splitter state in the session. Task-number: QTCREATORBUG-24690 Change-Id: Ifd27382cc61825f96de4fa5d4691b4f615448182 Reviewed-by: hjk Reviewed-by: Eike Ziller --- src/plugins/projectexplorer/panelswidget.cpp | 22 +++++++++---- src/plugins/projectexplorer/panelswidget.h | 6 ++++ .../projectexplorer/targetsettingspanel.cpp | 33 +++++++++++++++---- 3 files changed, 48 insertions(+), 13 deletions(-) diff --git a/src/plugins/projectexplorer/panelswidget.cpp b/src/plugins/projectexplorer/panelswidget.cpp index 488390e8226..1fd98512dc9 100644 --- a/src/plugins/projectexplorer/panelswidget.cpp +++ b/src/plugins/projectexplorer/panelswidget.cpp @@ -55,18 +55,18 @@ const int PANEL_LEFT_MARGIN = 70; // PanelsWidget /// -PanelsWidget::PanelsWidget(QWidget *parent) : QWidget(parent) +PanelsWidget::PanelsWidget(QWidget *parent) + : QWidget(parent), m_splitter(new Core::MiniSplitter(this)) { - const auto splitter = new Core::MiniSplitter(this); m_root = new QWidget(nullptr); m_root->setFocusPolicy(Qt::NoFocus); m_root->setContentsMargins(0, 0, 40, 0); - splitter->addWidget(m_root); - splitter->addWidget(new QWidget); - splitter->setStretchFactor(1, 100); // Force root widget to its minimum size initially + m_splitter->addWidget(m_root); + m_splitter->addWidget(new QWidget); + m_splitter->setStretchFactor(1, 100); // Force root widget to its minimum size initially const auto scroller = new QScrollArea(this); - scroller->setWidget(splitter); + scroller->setWidget(m_splitter); scroller->setFrameStyle(QFrame::NoFrame); scroller->setWidgetResizable(true); scroller->setFocusPolicy(Qt::NoFocus); @@ -153,4 +153,14 @@ void PanelsWidget::addPropertiesPanel(const QString &displayName, const QIcon &i m_layout->addWidget(widget, widgetRow, 0, 1, 2); } +QByteArray PanelsWidget::saveSplitterState() const +{ + return m_splitter->saveState().toHex(); +} + +void PanelsWidget::loadSplitterState(const QByteArray &state) +{ + m_splitter->restoreState(QByteArray::fromHex(state)); +} + } // ProjectExplorer diff --git a/src/plugins/projectexplorer/panelswidget.h b/src/plugins/projectexplorer/panelswidget.h index 1be7723aaad..35e57351f11 100644 --- a/src/plugins/projectexplorer/panelswidget.h +++ b/src/plugins/projectexplorer/panelswidget.h @@ -34,6 +34,8 @@ class QGridLayout; class QIcon; QT_END_NAMESPACE +namespace Core { class MiniSplitter; } + namespace ProjectExplorer { class PROJECTEXPLORER_EXPORT PanelsWidget : public QWidget @@ -49,8 +51,12 @@ public: void addPropertiesPanel(const QString &displayName, const QIcon &icon, QWidget *widget); + QByteArray saveSplitterState() const; + void loadSplitterState(const QByteArray &state); + private: QGridLayout *m_layout; + Core::MiniSplitter * const m_splitter; QWidget *m_root; }; diff --git a/src/plugins/projectexplorer/targetsettingspanel.cpp b/src/plugins/projectexplorer/targetsettingspanel.cpp index e5a25c0b5fc..5d6970710c0 100644 --- a/src/plugins/projectexplorer/targetsettingspanel.cpp +++ b/src/plugins/projectexplorer/targetsettingspanel.cpp @@ -613,13 +613,32 @@ public: QWidget *panel() const { if (!m_panel) { - m_panel = (m_subIndex == RunPage) - ? new PanelsWidget(RunSettingsWidget::tr("Run Settings"), - QIcon(":/projectexplorer/images/RunSettings.png"), - new RunSettingsWidget(target())) - : new PanelsWidget(QCoreApplication::translate("BuildSettingsPanel", "Build Settings"), - QIcon(":/projectexplorer/images/BuildSettings.png"), - new BuildSettingsWidget(target())); + QString splitterStateKey = "PanelSplitterState:" + + m_project->projectFilePath().toString() + ':'; + if (m_subIndex == RunPage) { + splitterStateKey += "Run"; + m_panel = new PanelsWidget(RunSettingsWidget::tr("Run Settings"), + QIcon(":/projectexplorer/images/RunSettings.png"), + new RunSettingsWidget(target())); + } else { + splitterStateKey += "Build"; + m_panel = new PanelsWidget(QCoreApplication::translate("BuildSettingsPanel", "Build Settings"), + QIcon(":/projectexplorer/images/BuildSettings.png"), + new BuildSettingsWidget(target())); + } + const auto panel = qobject_cast(m_panel.data()); + const auto loadSplitterValue = [panel, splitterStateKey] { + const QByteArray splitterState = SessionManager::value(splitterStateKey).toByteArray(); + if (!splitterState.isEmpty()) + panel->loadSplitterState(splitterState); + }; + loadSplitterValue(); + QObject::connect(SessionManager::instance(), &SessionManager::aboutToSaveSession, + panel, [panel, splitterStateKey] { + SessionManager::setValue(splitterStateKey, panel->saveSplitterState()); + }); + QObject::connect(SessionManager::instance(), &SessionManager::sessionLoaded, + panel, loadSplitterValue); } return m_panel; } From 3c281aa48394ed7c74ff076fffce99876637c2b8 Mon Sep 17 00:00:00 2001 From: David Schulz Date: Mon, 21 Sep 2020 14:49:47 +0200 Subject: [PATCH 10/10] Editor: Select moved text after drag and drop Fixes: QTCREATORBUG-24245 Change-Id: I9da52424128825f729d5d20e2c7fd095120477c6 Reviewed-by: Christian Stenger --- src/plugins/texteditor/texteditor.cpp | 53 ++++++++++++++++++++++++--- src/plugins/texteditor/texteditor.h | 1 + 2 files changed, 49 insertions(+), 5 deletions(-) diff --git a/src/plugins/texteditor/texteditor.cpp b/src/plugins/texteditor/texteditor.cpp index aec12dc75a9..0fdd28182cc 100644 --- a/src/plugins/texteditor/texteditor.cpp +++ b/src/plugins/texteditor/texteditor.cpp @@ -163,6 +163,8 @@ enum { NExtraSelectionKinds = 12 }; using TransformationMethod = QString(const QString &); using ListTransformationMethod = void(QStringList &); +static constexpr char dropProperty[] = "dropProp"; + class LineColumnLabel : public FixedSizeClickLabel { Q_OBJECT @@ -714,7 +716,7 @@ public: // block selection mode bool m_inBlockSelectionMode = false; QString copyBlockSelection(); - void insertIntoBlockSelection(const QString &text = QString()); + void insertIntoBlockSelection(const QString &text = QString(), const bool selectText = false); void setCursorToColumn(QTextCursor &cursor, int column, QTextCursor::MoveMode moveMode = QTextCursor::MoveAnchor); void removeBlockSelection(); @@ -3802,7 +3804,7 @@ void TextEditorWidgetPrivate::setCursorToColumn(QTextCursor &cursor, int column, cursor.block().text(), column), moveMode); } -void TextEditorWidgetPrivate::insertIntoBlockSelection(const QString &text) +void TextEditorWidgetPrivate::insertIntoBlockSelection(const QString &text, const bool selectText) { // TODO: add autocompleter support QTextCursor cursor = q->textCursor(); @@ -3828,6 +3830,7 @@ void TextEditorWidgetPrivate::insertIntoBlockSelection(const QString &text) int positionBlock = m_blockSelection.positionBlock; int anchorBlock = m_blockSelection.anchorBlock; int column = m_blockSelection.positionColumn; + const int anchorColumn = m_blockSelection.anchorColumn; const QTextBlock &firstBlock = m_document->document()->findBlockByNumber(m_blockSelection.firstBlockNumber()); @@ -3880,7 +3883,10 @@ void TextEditorWidgetPrivate::insertIntoBlockSelection(const QString &text) cursor.endEditBlock(); column += textLength; - m_blockSelection.fromPostition(positionBlock, column, anchorBlock, column); + m_blockSelection.fromPostition(positionBlock, + column, + anchorBlock, + selectText ? anchorColumn : column); q->doSetTextCursor(m_blockSelection.selection(m_document.data()), true); } @@ -7722,8 +7728,9 @@ void TextEditorWidget::insertFromMimeData(const QMimeData *source) if (d->m_codeAssistant.hasContext()) d->m_codeAssistant.destroyContext(); + const bool selectInsertedText = source->property(dropProperty).toBool(); if (d->m_inBlockSelectionMode) { - d->insertIntoBlockSelection(text); + d->insertIntoBlockSelection(text, selectInsertedText); return; } @@ -7738,7 +7745,16 @@ void TextEditorWidget::insertFromMimeData(const QMimeData *source) QTextCursor cursor = textCursor(); if (!tps.m_autoIndent) { cursor.beginEditBlock(); - cursor.insertText(text); + if (selectInsertedText) { + const int anchor = cursor.position(); + cursor.insertText(text); + const int pos = cursor.position(); + cursor.endEditBlock(); + cursor.setPosition(anchor); + cursor.setPosition(pos, QTextCursor::KeepAnchor); + } else { + cursor.insertText(text); + } cursor.endEditBlock(); setTextCursor(cursor); return; @@ -7768,6 +7784,9 @@ void TextEditorWidget::insertFromMimeData(const QMimeData *source) int cursorPosition = cursor.position(); cursor.insertText(text); + const QTextCursor endCursor = cursor; + QTextCursor startCursor = endCursor; + startCursor.setPosition(cursorPosition); int reindentBlockEnd = cursor.blockNumber() - (hasFinalNewline?1:0); @@ -7788,9 +7807,33 @@ void TextEditorWidget::insertFromMimeData(const QMimeData *source) } cursor.endEditBlock(); + if (selectInsertedText) { + cursor.setPosition(startCursor.position()); + cursor.setPosition(endCursor.position(), QTextCursor::KeepAnchor); + } setTextCursor(cursor); } +void TextEditorWidget::dropEvent(QDropEvent *e) +{ + const QMimeData *mime = e->mimeData(); + if (mime && (mime->hasText() || mime->hasHtml())) { + QMimeData *mimeOverwrite = duplicateMimeData(mime); + mimeOverwrite->setProperty(dropProperty, true); + auto dropOverwrite = new QDropEvent(e->pos(), + e->possibleActions(), + mimeOverwrite, + e->mouseButtons(), + e->keyboardModifiers()); + QPlainTextEdit::dropEvent(dropOverwrite); + e->setAccepted(dropOverwrite->isAccepted()); + delete dropOverwrite; + delete mimeOverwrite; + } else { + QPlainTextEdit::dropEvent(e); + } +} + QMimeData *TextEditorWidget::duplicateMimeData(const QMimeData *source) { Q_ASSERT(source); diff --git a/src/plugins/texteditor/texteditor.h b/src/plugins/texteditor/texteditor.h index 1e4ab92497c..6e693e36978 100644 --- a/src/plugins/texteditor/texteditor.h +++ b/src/plugins/texteditor/texteditor.h @@ -530,6 +530,7 @@ protected: QMimeData *createMimeDataFromSelection() const override; bool canInsertFromMimeData(const QMimeData *source) const override; void insertFromMimeData(const QMimeData *source) override; + void dropEvent(QDropEvent *e) override; virtual QString plainTextFromSelection(const QTextCursor &cursor) const; static QString convertToPlainText(const QString &txt);