From fb063a09bea0046c7ac72b9fc4d8fb563cfed06d Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Mon, 11 Sep 2017 15:47:35 +0200 Subject: [PATCH 01/13] AutoTest: Be more correct when gathering buildsystem targets This avoids taking too many buildsystem targets into account. On the downside this breaks execution of several possible project layouts. Change-Id: Ia7bf00d11a3e7c9bf362667e33b1d1542495db4a Reviewed-by: Oliver Wolff --- src/plugins/autotest/gtest/gtesttreeitem.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/plugins/autotest/gtest/gtesttreeitem.cpp b/src/plugins/autotest/gtest/gtesttreeitem.cpp index 92d24bc5a39..6828d4aa78d 100644 --- a/src/plugins/autotest/gtest/gtesttreeitem.cpp +++ b/src/plugins/autotest/gtest/gtesttreeitem.cpp @@ -29,6 +29,7 @@ #include #include +#include #include namespace Autotest { @@ -293,11 +294,16 @@ QSet GTestTreeItem::internalTargets() const QSet result; const auto cppMM = CppTools::CppModelManager::instance(); const auto projectInfo = cppMM->projectInfo(ProjectExplorer::SessionManager::startupProject()); + const QString file = filePath(); for (const CppTools::ProjectPart::Ptr projectPart : projectInfo.projectParts()) { if (projectPart->buildTargetType != CppTools::ProjectPart::Executable) continue; - if (projectPart->projectFile == proFile()) + if (projectPart->projectFile == proFile() + && Utils::anyOf(projectPart->files, [&file] (const CppTools::ProjectFile &pf) { + return pf.path == file; + })) { result.insert(projectPart->buildSystemTarget + '|' + projectPart->projectFile); + } } return result; } From 3c602b32d4914768465e0b226b2f996081333e08 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Wed, 13 Sep 2017 10:32:39 +0200 Subject: [PATCH 02/13] AutoTest: Try harder to find relevant build targets If there are tests defined or registered inside libraries we ended up trying to execute the library or nothing at all. If possible try to find correct build targets for such cases. Change-Id: I58e9edb7f858e3e5407ece6fcb8782f5a129acd0 Reviewed-by: Nikolai Kosjar --- src/plugins/autotest/gtest/gtesttreeitem.cpp | 4 +-- src/plugins/autotest/testtreeitem.cpp | 30 ++++++++++++++++++-- src/plugins/autotest/testtreeitem.h | 5 ++++ src/plugins/cpptools/cpptoolsplugin.cpp | 24 ++++++++++------ src/plugins/cpptools/cpptoolsreuse.h | 5 +++- 5 files changed, 53 insertions(+), 15 deletions(-) diff --git a/src/plugins/autotest/gtest/gtesttreeitem.cpp b/src/plugins/autotest/gtest/gtesttreeitem.cpp index 6828d4aa78d..3b2c680fe98 100644 --- a/src/plugins/autotest/gtest/gtesttreeitem.cpp +++ b/src/plugins/autotest/gtest/gtesttreeitem.cpp @@ -296,13 +296,13 @@ QSet GTestTreeItem::internalTargets() const const auto projectInfo = cppMM->projectInfo(ProjectExplorer::SessionManager::startupProject()); const QString file = filePath(); for (const CppTools::ProjectPart::Ptr projectPart : projectInfo.projectParts()) { - if (projectPart->buildTargetType != CppTools::ProjectPart::Executable) - continue; if (projectPart->projectFile == proFile() && Utils::anyOf(projectPart->files, [&file] (const CppTools::ProjectFile &pf) { return pf.path == file; })) { result.insert(projectPart->buildSystemTarget + '|' + projectPart->projectFile); + if (projectPart->buildTargetType != CppTools::ProjectPart::Executable) + result.unite(TestTreeItem::dependingInternalTargets(cppMM, file)); } } return result; diff --git a/src/plugins/autotest/testtreeitem.cpp b/src/plugins/autotest/testtreeitem.cpp index 626fda93d3b..d27c689e5b0 100644 --- a/src/plugins/autotest/testtreeitem.cpp +++ b/src/plugins/autotest/testtreeitem.cpp @@ -30,6 +30,7 @@ #include #include +#include #include #include @@ -286,12 +287,12 @@ bool TestTreeItem::lessThan(const TestTreeItem *other, SortMode mode) const QSet TestTreeItem::internalTargets() const { auto cppMM = CppTools::CppModelManager::instance(); - const QList projectParts = cppMM->projectPart(filePath()); + const QList projectParts = cppMM->projectPart(m_filePath); QSet targets; for (const CppTools::ProjectPart::Ptr part : projectParts) { - if (part->buildTargetType != CppTools::ProjectPart::Executable) - continue; targets.insert(part->buildSystemTarget + '|' + part->projectFile); + if (part->buildTargetType != CppTools::ProjectPart::Executable) + targets.unite(TestTreeItem::dependingInternalTargets(cppMM, m_filePath)); } return targets; } @@ -359,5 +360,28 @@ TestTreeItem *TestTreeItem::findChildBy(CompareFunction compare) const return nullptr; } +/* + * try to find build system target that depends on the given file - if the file is no header + * try to find the corresponding header and use this instead to find the respective target + */ +QSet TestTreeItem::dependingInternalTargets(CppTools::CppModelManager *cppMM, + const QString &file) +{ + QSet result; + QTC_ASSERT(cppMM, return result); + const CPlusPlus::Snapshot snapshot = cppMM->snapshot(); + QTC_ASSERT(snapshot.contains(file), return result); + bool wasHeader; + const QString correspondingFile + = CppTools::correspondingHeaderOrSource(file, &wasHeader, CppTools::CacheUsage::ReadOnly); + const Utils::FileNameList dependingFiles = snapshot.filesDependingOn( + wasHeader ? file : correspondingFile); + for (const Utils::FileName &fn : dependingFiles) { + for (const CppTools::ProjectPart::Ptr part : cppMM->projectPart(fn)) + result.insert(part->buildSystemTarget + '|' + part->projectFile); + } + return result; +} + } // namespace Internal } // namespace Autotest diff --git a/src/plugins/autotest/testtreeitem.h b/src/plugins/autotest/testtreeitem.h index 2c2c728a2c7..f4a7d735db5 100644 --- a/src/plugins/autotest/testtreeitem.h +++ b/src/plugins/autotest/testtreeitem.h @@ -28,6 +28,7 @@ #include #include +#include #include #include @@ -40,6 +41,8 @@ namespace { }; } +namespace CppTools { class CppModelManager; } + namespace Autotest { namespace Internal { @@ -114,6 +117,8 @@ public: protected: typedef std::function CompareFunction; TestTreeItem *findChildBy(CompareFunction compare) const; + static QSet dependingInternalTargets(CppTools::CppModelManager *cppMM, + const QString &file); private: void revalidateCheckState(); diff --git a/src/plugins/cpptools/cpptoolsplugin.cpp b/src/plugins/cpptools/cpptoolsplugin.cpp index d0dfec3a56d..af192cb0828 100644 --- a/src/plugins/cpptools/cpptoolsplugin.cpp +++ b/src/plugins/cpptools/cpptoolsplugin.cpp @@ -357,7 +357,8 @@ static int commonFilePathLength(const QString &s1, const QString &s2) static QString correspondingHeaderOrSourceInProject(const QFileInfo &fileInfo, const QStringList &candidateFileNames, - const ProjectExplorer::Project *project) + const ProjectExplorer::Project *project, + CacheUsage cacheUsage) { QString bestFileName; int compareValue = 0; @@ -376,8 +377,10 @@ static QString correspondingHeaderOrSourceInProject(const QFileInfo &fileInfo, if (!bestFileName.isEmpty()) { const QFileInfo candidateFi(bestFileName); QTC_ASSERT(candidateFi.isFile(), return QString()); - m_headerSourceMapping[fileInfo.absoluteFilePath()] = candidateFi.absoluteFilePath(); - m_headerSourceMapping[candidateFi.absoluteFilePath()] = fileInfo.absoluteFilePath(); + if (cacheUsage == CacheUsage::ReadWrite) { + m_headerSourceMapping[fileInfo.absoluteFilePath()] = candidateFi.absoluteFilePath(); + m_headerSourceMapping[candidateFi.absoluteFilePath()] = fileInfo.absoluteFilePath(); + } return candidateFi.absoluteFilePath(); } @@ -386,7 +389,7 @@ static QString correspondingHeaderOrSourceInProject(const QFileInfo &fileInfo, } // namespace Internal -QString correspondingHeaderOrSource(const QString &fileName, bool *wasHeader) +QString correspondingHeaderOrSource(const QString &fileName, bool *wasHeader, CacheUsage cacheUsage) { using namespace Internal; @@ -437,9 +440,11 @@ QString correspondingHeaderOrSource(const QString &fileName, bool *wasHeader) const QString normalized = Utils::FileUtils::normalizePathName(candidateFilePath); const QFileInfo candidateFi(normalized); if (candidateFi.isFile()) { - m_headerSourceMapping[fi.absoluteFilePath()] = candidateFi.absoluteFilePath(); - if (!isHeader || !baseName.endsWith(privateHeaderSuffix)) - m_headerSourceMapping[candidateFi.absoluteFilePath()] = fi.absoluteFilePath(); + if (cacheUsage == CacheUsage::ReadWrite) { + m_headerSourceMapping[fi.absoluteFilePath()] = candidateFi.absoluteFilePath(); + if (!isHeader || !baseName.endsWith(privateHeaderSuffix)) + m_headerSourceMapping[candidateFi.absoluteFilePath()] = fi.absoluteFilePath(); + } return candidateFi.absoluteFilePath(); } } @@ -449,7 +454,7 @@ QString correspondingHeaderOrSource(const QString &fileName, bool *wasHeader) ProjectExplorer::Project *currentProject = ProjectExplorer::ProjectTree::currentProject(); if (currentProject) { const QString path = correspondingHeaderOrSourceInProject(fi, candidateFileNames, - currentProject); + currentProject, cacheUsage); if (!path.isEmpty()) return path; @@ -462,7 +467,8 @@ QString correspondingHeaderOrSource(const QString &fileName, bool *wasHeader) if (project == currentProject) continue; // We have already checked the current project. - const QString path = correspondingHeaderOrSourceInProject(fi, candidateFileNames, project); + const QString path = correspondingHeaderOrSourceInProject(fi, candidateFileNames, + project, cacheUsage); if (!path.isEmpty()) return path; } diff --git a/src/plugins/cpptools/cpptoolsreuse.h b/src/plugins/cpptools/cpptoolsreuse.h index 46ef50d7b16..89183bb0b81 100644 --- a/src/plugins/cpptools/cpptoolsreuse.h +++ b/src/plugins/cpptools/cpptoolsreuse.h @@ -68,7 +68,10 @@ bool CPPTOOLS_EXPORT isOwnershipRAIIType(CPlusPlus::Symbol *symbol, const CPlusPlus::Macro CPPTOOLS_EXPORT *findCanonicalMacro(const QTextCursor &cursor, CPlusPlus::Document::Ptr document); -QString CPPTOOLS_EXPORT correspondingHeaderOrSource(const QString &fileName, bool *wasHeader = 0); +enum class CacheUsage { ReadWrite, ReadOnly }; + +QString CPPTOOLS_EXPORT correspondingHeaderOrSource(const QString &fileName, bool *wasHeader = 0, + CacheUsage cacheUsage = CacheUsage::ReadWrite); void CPPTOOLS_EXPORT switchHeaderSource(); class CppCodeModelSettings; From 090dea66eea8a29dd3c7a798927dc7610c2d11ce Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Wed, 13 Sep 2017 11:03:29 +0200 Subject: [PATCH 03/13] AutoTest: Use single build target as fallback If we cannot find the respective build target to execute tests, but we only have a single build target then we now assume that this will be the right one. Change-Id: I0f7c3c4f371bce3a7f328e7c28dc61cadf7f6e9e Reviewed-by: Oliver Wolff --- src/plugins/autotest/testconfiguration.cpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/plugins/autotest/testconfiguration.cpp b/src/plugins/autotest/testconfiguration.cpp index 396fbb4f1c8..1bdb794abdf 100644 --- a/src/plugins/autotest/testconfiguration.cpp +++ b/src/plugins/autotest/testconfiguration.cpp @@ -90,7 +90,7 @@ void TestConfiguration::completeTestInformation(TestRunMode runMode) const QSet buildSystemTargets = m_buildTargets; qCDebug(LOG) << "BuildSystemTargets\n " << buildSystemTargets; - const BuildTargetInfo targetInfo + BuildTargetInfo targetInfo = Utils::findOrDefault(target->applicationTargets().list, [&buildSystemTargets] (const BuildTargetInfo &bti) { return Utils::anyOf(buildSystemTargets, [&bti](const QString &b) { @@ -101,11 +101,19 @@ void TestConfiguration::completeTestInformation(TestRunMode runMode) && targWithProjectFile.at(1).startsWith(bti.projectFilePath.toString()); }); }); - if (!QTC_GUARD(!targetInfo.targetFilePath.isEmpty())) { // empty if BTI default created + // we might end up with an empty targetFilePath - e.g. when having a library we just link to + // there would be no BuildTargetInfo that could match + if (targetInfo.targetFilePath.isEmpty()) { qCDebug(LOG) << "BuildTargetInfos"; - for (const BuildTargetInfo &bti : target->applicationTargets().list) - qCDebug(LOG) << " " << bti.targetName << bti.projectFilePath << bti.targetFilePath; + const QList buildTargets = target->applicationTargets().list; + // if there is only one build target just use it (but be honest that we're guessing) + if (buildTargets.size() == 1) { + targetInfo = buildTargets.first(); + m_guessedConfiguration = true; + m_guessedFrom = targetInfo.targetName; + } } + const QString localExecutable = ensureExeEnding(targetInfo.targetFilePath.toString()); QString buildBase; From 9dc8b54cdb48578992f8bb9c7349fcf2d2193a89 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Fri, 22 Sep 2017 12:19:13 +0200 Subject: [PATCH 04/13] AutoTest: Early return if fail to get local executable If we have not found a local executable any further processing is not necessary as the outcome will be the same: we will not be able to start the test runnable. Change-Id: Iaa4bbd533ced6184148f941c1cba394f9f47554d Reviewed-by: Oliver Wolff --- src/plugins/autotest/testconfiguration.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/plugins/autotest/testconfiguration.cpp b/src/plugins/autotest/testconfiguration.cpp index 1bdb794abdf..00f3f0dc31d 100644 --- a/src/plugins/autotest/testconfiguration.cpp +++ b/src/plugins/autotest/testconfiguration.cpp @@ -115,6 +115,8 @@ void TestConfiguration::completeTestInformation(TestRunMode runMode) } const QString localExecutable = ensureExeEnding(targetInfo.targetFilePath.toString()); + if (localExecutable.isEmpty()) + return; QString buildBase; if (auto buildConfig = target->activeBuildConfiguration()) { From 1e8d030284fc14aa01348d8a12f805e5f5019ccf Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Wed, 13 Sep 2017 14:27:20 +0200 Subject: [PATCH 05/13] AutoTest: Ask for runnable if determination failed There are several complex project layouts that lead to failing to determine the correct runnable for tests. If this happens prompt the user for the runnable to use instead of performing wild guesses or blindly using a wrong one. Task-number: QTCREATORBUG-17882 Task-number: QTCREATORBUG-18922 Task-number: QTCREATORBUG-18932 Change-Id: I1575f310c450e56c087f1e689d0fc7dfb0cd0bef Reviewed-by: Oliver Wolff --- src/plugins/autotest/testconfiguration.cpp | 72 +++++++++- src/plugins/autotest/testconfiguration.h | 8 +- src/plugins/autotest/testrunner.cpp | 149 +++++++++++++++++++++ src/plugins/autotest/testrunner.h | 25 ++++ 4 files changed, 250 insertions(+), 4 deletions(-) diff --git a/src/plugins/autotest/testconfiguration.cpp b/src/plugins/autotest/testconfiguration.cpp index 00f3f0dc31d..b4af50e8a99 100644 --- a/src/plugins/autotest/testconfiguration.cpp +++ b/src/plugins/autotest/testconfiguration.cpp @@ -72,11 +72,66 @@ static QString ensureExeEnding(const QString& file) return Utils::HostOsInfo::withExecutableSuffix(file); } +void TestConfiguration::completeTestInformation(ProjectExplorer::RunConfiguration *rc, + TestRunMode runMode) +{ + QTC_ASSERT(rc, return); + Project *project = SessionManager::startupProject(); + if (!project) + return; + + Target *target = project->activeTarget(); + if (!target) + return; + + if (!Utils::findOr(target->runConfigurations(), nullptr, + [&rc] (RunConfiguration *config) { return rc == config; })) { + return; + } + + Runnable runnable = rc->runnable(); + if (!runnable.is()) + return; + m_runnable = runnable.as(); + m_displayName = rc->displayName(); + m_project = rc->project(); + + const QString buildSystemTarget = rc->buildSystemTarget(); + BuildTargetInfo targetInfo + = Utils::findOrDefault(target->applicationTargets().list, + [&buildSystemTarget] (const BuildTargetInfo &bti) { + return bti.targetName == buildSystemTarget; + }); + if (!targetInfo.targetFilePath.isEmpty()) + m_runnable.executable = ensureExeEnding(targetInfo.targetFilePath.toString()); + + QString buildBase; + if (auto buildConfig = target->activeBuildConfiguration()) { + buildBase = buildConfig->buildDirectory().toString(); + const QString projBase = m_project->projectDirectory().toString(); + if (m_projectFile.startsWith(projBase)) + m_buildDir = QFileInfo(buildBase + m_projectFile.mid(projBase.length())).absolutePath(); + } + if (runMode == TestRunMode::Debug || runMode == TestRunMode::DebugWithoutDeploy) + m_runConfig = new TestRunConfiguration(rc->target(), this); +} + void TestConfiguration::completeTestInformation(TestRunMode runMode) { QTC_ASSERT(!m_projectFile.isEmpty(), return); QTC_ASSERT(!m_buildTargets.isEmpty(), return); + if (m_origRunConfig) { + qCDebug(LOG) << "Using run configuration specified by user or found by first call"; + completeTestInformation(m_origRunConfig, runMode); + if (hasExecutable()) { + qCDebug(LOG) << "Completed.\nRunnable:" << m_runnable.executable + << "\nArgs:" << m_runnable.commandLineArguments + << "\nWorking directory:" << m_runnable.workingDirectory; + return; + } + qCDebug(LOG) << "Failed to complete - using 'normal' way."; + } Project *project = SessionManager::startupProject(); if (!project) return; @@ -163,6 +218,7 @@ void TestConfiguration::completeTestInformation(TestRunMode runMode) return b.startsWith(currentBST); }))) { qCDebug(LOG) << " Using this RunConfig."; + m_origRunConfig = runConfig; m_runnable = stdRunnable; m_runnable.executable = currentExecutable; m_displayName = runConfig->displayName(); @@ -177,9 +233,9 @@ void TestConfiguration::completeTestInformation(TestRunMode runMode) // or we might have end up using the (wrong) path of a locally installed executable // for this case try the original executable path of the BuildTargetInfo (the executable // before installation) to have at least something to execute - if (m_runnable.executable.isEmpty() && !localExecutable.isEmpty()) + if (!hasExecutable() && !localExecutable.isEmpty()) m_runnable.executable = localExecutable; - if (m_displayName.isEmpty() && !m_runnable.executable.isEmpty()) { + if (m_displayName.isEmpty() && hasExecutable()) { qCDebug(LOG) << " Fallback"; // we failed to find a valid runconfiguration - but we've got the executable already if (auto rc = target->activeRunConfiguration()) { @@ -265,9 +321,14 @@ void TestConfiguration::setInternalTargets(const QSet &targets) m_buildTargets = targets; } +void TestConfiguration::setOriginalRunConfiguration(RunConfiguration *runConfig) +{ + m_origRunConfig = runConfig; +} + QString TestConfiguration::executableFilePath() const { - if (m_runnable.executable.isEmpty()) + if (!hasExecutable()) return QString(); QFileInfo commandFileInfo(m_runnable.executable); @@ -305,5 +366,10 @@ bool DebuggableTestConfiguration::isDebugRunMode() const return m_runMode == TestRunMode::Debug || m_runMode == TestRunMode::DebugWithoutDeploy; } +bool TestConfiguration::hasExecutable() const +{ + return !m_runnable.executable.isEmpty(); +} + } // namespace Internal } // namespace Autotest diff --git a/src/plugins/autotest/testconfiguration.h b/src/plugins/autotest/testconfiguration.h index 7ec208af2a9..e35b0f0dd21 100644 --- a/src/plugins/autotest/testconfiguration.h +++ b/src/plugins/autotest/testconfiguration.h @@ -56,6 +56,7 @@ public: virtual ~TestConfiguration(); void completeTestInformation(TestRunMode runMode); + void completeTestInformation(ProjectExplorer::RunConfiguration *rc, TestRunMode runMode); void setTestCases(const QStringList &testCases); void setTestCaseCount(int count); @@ -67,6 +68,7 @@ public: void setEnvironment(const Utils::Environment &env); void setProject(ProjectExplorer::Project *project); void setInternalTargets(const QSet &targets); + void setOriginalRunConfiguration(ProjectExplorer::RunConfiguration *runConfig); QStringList testCases() const { return m_testCases; } int testCaseCount() const { return m_testCaseCount; } @@ -77,7 +79,10 @@ public: QString displayName() const { return m_displayName; } Utils::Environment environment() const { return m_runnable.environment; } ProjectExplorer::Project *project() const { return m_project.data(); } + QSet internalTargets() const { return m_buildTargets; } + ProjectExplorer::RunConfiguration *originalRunConfiguration() const { return m_origRunConfig; } TestRunConfiguration *runConfiguration() const { return m_runConfig; } + bool hasExecutable() const; bool isGuessed() const { return m_guessedConfiguration; } QString runConfigDisplayName() const { return m_guessedConfiguration ? m_guessedFrom : m_displayName; } @@ -96,8 +101,9 @@ private: QString m_guessedFrom; QPointer m_project; bool m_guessedConfiguration = false; - TestRunConfiguration *m_runConfig = 0; + TestRunConfiguration *m_runConfig = nullptr; QSet m_buildTargets; + ProjectExplorer::RunConfiguration *m_origRunConfig = nullptr; ProjectExplorer::StandardRunnable m_runnable; }; diff --git a/src/plugins/autotest/testrunner.cpp b/src/plugins/autotest/testrunner.cpp index 4c9ba7f645d..b263f44e557 100644 --- a/src/plugins/autotest/testrunner.cpp +++ b/src/plugins/autotest/testrunner.cpp @@ -32,6 +32,7 @@ #include "testsettings.h" #include "testoutputreader.h" +#include #include #include @@ -39,19 +40,28 @@ #include #include #include +#include +#include #include #include #include #include +#include +#include +#include #include #include +#include +#include #include #include #include +#include + namespace Autotest { namespace Internal { @@ -284,8 +294,57 @@ void TestRunner::prepareToRunTests(TestRunMode mode) } } +static QString firstTestCaseTarget(const TestConfiguration *config) +{ + const QSet &internalTargets = config->internalTargets(); + int size = internalTargets.size(); + if (size) + return (*internalTargets.begin()).split('|').first(); + return TestRunner::tr(""); +} + +static bool askUserForRunConfiguration(TestConfiguration *config) +{ + using namespace ProjectExplorer; + RunConfigurationSelectionDialog dialog(firstTestCaseTarget(config), + Core::ICore::dialogParent()); + if (dialog.exec() == QDialog::Accepted) { + const QString dName = dialog.displayName(); + if (dName.isEmpty()) + return false; + // run configuration has been selected - fill config based on this one.. + const QString exe = dialog.executable(); + // paranoia... can the current startup project have changed meanwhile? + if (auto project = SessionManager::startupProject()) { + if (auto target = project->activeTarget()) { + RunConfiguration *runConfig + = Utils::findOr(target->runConfigurations(), nullptr, + [&dName, &exe] (const RunConfiguration *rc) { + if (rc->displayName() != dName) + return false; + if (!rc->runnable().is()) + return false; + StandardRunnable runnable = rc->runnable().as(); + return runnable.executable == exe; + }); + if (runConfig) { + config->setOriginalRunConfiguration(runConfig); + return true; + } + } + } + } + return false; +} + void TestRunner::runTests() { + for (TestConfiguration *config : m_selectedTests) { + config->completeTestInformation(TestRunMode::Run); + if (!config->hasExecutable()) + if (askUserForRunConfiguration(config)) + config->completeTestInformation(config->originalRunConfiguration(), TestRunMode::Run); + } QFuture future = Utils::runAsync(&performTestRun, m_selectedTests, *AutotestPlugin::instance()->settings()); m_futureWatcher.setFuture(future); @@ -327,6 +386,11 @@ void TestRunner::debugTests() TestConfiguration *config = m_selectedTests.first(); config->completeTestInformation(TestRunMode::Debug); + if (!config->hasExecutable()) { + if (askUserForRunConfiguration(config)) + config->completeTestInformation(config->originalRunConfiguration(), TestRunMode::Debug); + } + if (!config->runConfiguration()) { emit testResultReady(TestResultPtr(new FaultyTestResult(Result::MessageFatal, TestRunner::tr("Failed to get run configuration.")))); @@ -453,5 +517,90 @@ void TestRunner::onFinished() emit testRunFinished(); } +/*************************************************************************************************/ + +RunConfigurationSelectionDialog::RunConfigurationSelectionDialog(const QString &testsInfo, + QWidget *parent) + : QDialog(parent) +{ + setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); + setWindowTitle(tr("Select Run Configuration")); + + m_details = new QLabel(tr("Could not determine which run configuration to choose for running" + " tests (%1)").arg(testsInfo), this); + m_rcCombo = new QComboBox(this); + m_executable = new QLabel(this); + m_arguments = new QLabel(this); + m_workingDir = new QLabel(this); + m_buttonBox = new QDialogButtonBox(this); + m_buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok); + m_buttonBox->button(QDialogButtonBox::Ok)->setDefault(true); + + auto line = new QFrame(this); + line->setFrameShape(QFrame::HLine); + line->setFrameShadow(QFrame::Sunken); + + auto formLayout = new QFormLayout; + formLayout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow); + formLayout->addRow(m_details); + formLayout->addRow(tr("Run Configuration:"), m_rcCombo); + formLayout->addRow(line); + formLayout->addRow(tr("Executable:"), m_executable); + formLayout->addRow(tr("Arguments:"), m_arguments); + formLayout->addRow(tr("Working Directory:"), m_workingDir); + // TODO Device support + auto vboxLayout = new QVBoxLayout(this); + vboxLayout->addLayout(formLayout); + vboxLayout->addStretch(); + vboxLayout->addWidget(line); + vboxLayout->addWidget(m_buttonBox); + + connect(m_rcCombo, &QComboBox::currentTextChanged, + this, &RunConfigurationSelectionDialog::updateLabels); + connect(m_buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept); + connect(m_buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject); + + populate(); +} + +QString RunConfigurationSelectionDialog::displayName() const +{ + return m_rcCombo ? m_rcCombo->currentText() : QString(); +} + +QString RunConfigurationSelectionDialog::executable() const +{ + return m_executable ? m_executable->text() : QString(); +} + +void RunConfigurationSelectionDialog::populate() +{ + m_rcCombo->addItem(QString(), QStringList({QString(), QString(), QString()})); // empty default + + if (auto project = ProjectExplorer::SessionManager::startupProject()) { + if (auto target = project->activeTarget()) { + for (ProjectExplorer::RunConfiguration *rc : target->runConfigurations()) { + if (rc->runnable().is()) { + auto runnable = rc->runnable().as(); + const QStringList rcDetails = { runnable.executable, + runnable.commandLineArguments, + runnable.workingDirectory }; + m_rcCombo->addItem(rc->displayName(), rcDetails); + } + } + } + } +} + +void RunConfigurationSelectionDialog::updateLabels() +{ + int i = m_rcCombo->currentIndex(); + const QStringList values = m_rcCombo->itemData(i).toStringList(); + QTC_ASSERT(values.size() == 3, return); + m_executable->setText(values.at(0)); + m_arguments->setText(values.at(1)); + m_workingDir->setText(values.at(2)); +} + } // namespace Internal } // namespace Autotest diff --git a/src/plugins/autotest/testrunner.h b/src/plugins/autotest/testrunner.h index b146d7fb95e..004c4f48313 100644 --- a/src/plugins/autotest/testrunner.h +++ b/src/plugins/autotest/testrunner.h @@ -28,10 +28,17 @@ #include "testconfiguration.h" #include "testresult.h" +#include #include #include #include +QT_BEGIN_NAMESPACE +class QComboBox; +class QDialogButtonBox; +class QLabel; +QT_END_NAMESPACE + namespace ProjectExplorer { class Project; } @@ -77,5 +84,23 @@ private: QMetaObject::Connection m_buildConnect; }; +class RunConfigurationSelectionDialog : public QDialog +{ + Q_OBJECT +public: + explicit RunConfigurationSelectionDialog(const QString &testsInfo, QWidget *parent = nullptr); + QString displayName() const; + QString executable() const; +private: + void populate(); + void updateLabels(); + QLabel *m_details; + QLabel *m_executable; + QLabel *m_arguments; + QLabel *m_workingDir; + QComboBox *m_rcCombo; + QDialogButtonBox *m_buttonBox; +}; + } // namespace Internal } // namespace Autotest From 05ef571922e8dcda70b89f9c9f2797ae11f205df Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Tue, 26 Sep 2017 10:24:31 +0200 Subject: [PATCH 06/13] QmlProfiler: 20s are still not enough for LocalQmlProfilerRunnerTest The test has failed again because of insufficient timeout. 22s would have been enough this time ... Change-Id: I001a921921997863d77af8483403a8bd8a85eb29 Reviewed-by: Christian Kandeler --- .../tests/localqmlprofilerrunner_test.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/plugins/qmlprofiler/tests/localqmlprofilerrunner_test.cpp b/src/plugins/qmlprofiler/tests/localqmlprofilerrunner_test.cpp index 754455c86b4..3bf680be5ba 100644 --- a/src/plugins/qmlprofiler/tests/localqmlprofilerrunner_test.cpp +++ b/src/plugins/qmlprofiler/tests/localqmlprofilerrunner_test.cpp @@ -93,8 +93,8 @@ void LocalQmlProfilerRunnerTest::testRunner() runControl->initiateStart(); - QTRY_COMPARE_WITH_TIMEOUT(startCount, 1, 20000); - QTRY_VERIFY_WITH_TIMEOUT(!started, 20000); + QTRY_COMPARE_WITH_TIMEOUT(startCount, 1, 30000); + QTRY_VERIFY_WITH_TIMEOUT(!started, 30000); QCOMPARE(stopCount, 1); QCOMPARE(runCount, 0); @@ -114,8 +114,8 @@ void LocalQmlProfilerRunnerTest::testRunner() connectRunner(); runControl->initiateStart(); - QTRY_VERIFY_WITH_TIMEOUT(running, 20000); - QTRY_VERIFY_WITH_TIMEOUT(!running, 20000); + QTRY_VERIFY_WITH_TIMEOUT(running, 30000); + QTRY_VERIFY_WITH_TIMEOUT(!running, 30000); QCOMPARE(startCount, 2); QCOMPARE(stopCount, 2); QCOMPARE(runCount, 1); @@ -134,9 +134,9 @@ void LocalQmlProfilerRunnerTest::testRunner() connectRunner(); runControl->initiateStart(); - QTRY_VERIFY_WITH_TIMEOUT(running, 20000); + QTRY_VERIFY_WITH_TIMEOUT(running, 30000); runControl->initiateStop(); - QTRY_VERIFY_WITH_TIMEOUT(!running, 20000); + QTRY_VERIFY_WITH_TIMEOUT(!running, 30000); QCOMPARE(startCount, 3); QCOMPARE(stopCount, 3); QCOMPARE(runCount, 2); From cf370d53050a835461c56f9ee6a131d08ce9629f Mon Sep 17 00:00:00 2001 From: Robert Loehning Date: Thu, 14 Sep 2017 14:36:26 +0200 Subject: [PATCH 07/13] Squish: Update debugger tests The used project looks a little different now. Change-Id: I786749a4aae5d2ceaff0d2fc65aedf41c04a66f2 Reviewed-by: Christian Stenger --- .../system/suite_debugger/tst_simple_analyze/test.py | 4 +++- .../tst_simple_analyze/testdata/events_qt5.tsv | 11 ----------- tests/system/suite_debugger/tst_simple_debug/test.py | 6 ++++-- 3 files changed, 7 insertions(+), 14 deletions(-) diff --git a/tests/system/suite_debugger/tst_simple_analyze/test.py b/tests/system/suite_debugger/tst_simple_analyze/test.py index 89c5fe30919..d01d5cbc966 100644 --- a/tests/system/suite_debugger/tst_simple_analyze/test.py +++ b/tests/system/suite_debugger/tst_simple_analyze/test.py @@ -35,7 +35,9 @@ def main(): analyzerTargets = Targets.desktopTargetClasses() checkedTargets, projectName = createNewQtQuickApplication(workingDir, targets=analyzerTargets) editor = waitForObject(":Qt Creator_QmlJSEditor::QmlJSTextEditorWidget") - if placeCursorToLine(editor, "MouseArea.*", True): + if placeCursorToLine(editor, "}"): + type(editor, '') + type(editor, '') type(editor, '') type(editor, '') typeLines(editor, ['Timer {', diff --git a/tests/system/suite_debugger/tst_simple_analyze/testdata/events_qt5.tsv b/tests/system/suite_debugger/tst_simple_analyze/testdata/events_qt5.tsv index 7e1b41e3422..cd25a9eb10b 100644 --- a/tests/system/suite_debugger/tst_simple_analyze/testdata/events_qt5.tsv +++ b/tests/system/suite_debugger/tst_simple_analyze/testdata/events_qt5.tsv @@ -3,18 +3,7 @@ "main.qml:15" "Handling Signal" "2" "onTriggered: { runCount += 1; var i; for (i = 1; i < 2500; ++i) { var j = i * i; console.log(j); } }" "main.qml:15" "JavaScript" "2" "onTriggered" "main.qml:4" "Creating" "2" "QtQuick.Window/Window" -"main.qml:33" "Creating" "2" "QtQuick/TextEdit" "main.qml:1" "Compiling" "1" "main.qml" "main.qml:10" "Creating" "2" "QtQuick/Timer" -"main.qml:37" "Binding" "1" "anchors.top: parent.top" -"main.qml:40" "Creating" "2" "QtQuick/Rectangle" -"main.qml:37" "JavaScript" "1" "expression for top" "main.qml:14" "Binding" "3" "running: runCount < 2" -"main.qml:26" "Creating" "2" "QtQuick/MouseArea" -"main.qml:38" "Binding" "1" "anchors.horizontalCenter: parent.horizontalCenter" -"main.qml:38" "JavaScript" "1" "expression for horizontalCenter" -"main.qml:41" "Binding" "1" "anchors.fill: parent" -"main.qml:27" "Binding" "1" "anchors.fill: parent" "main.qml:14" "JavaScript" "3" "expression for running" -"main.qml:41" "JavaScript" "1" "expression for fill" -"main.qml:27" "JavaScript" "1" "expression for fill" diff --git a/tests/system/suite_debugger/tst_simple_debug/test.py b/tests/system/suite_debugger/tst_simple_debug/test.py index 54b0d652ee5..c726d6468bb 100644 --- a/tests/system/suite_debugger/tst_simple_debug/test.py +++ b/tests/system/suite_debugger/tst_simple_debug/test.py @@ -35,7 +35,9 @@ def main(): workingDir = tempDir() checkedTargets, projectName = createNewQtQuickApplication(workingDir, targets=targets) editor = waitForObject(":Qt Creator_QmlJSEditor::QmlJSTextEditorWidget") - if placeCursorToLine(editor, "MouseArea.*", True): + if placeCursorToLine(editor, "}"): + type(editor, '') + type(editor, '') type(editor, '') type(editor, '') typeLines(editor, ['Timer {', @@ -50,7 +52,7 @@ def main(): test.log("Setting breakpoints") result = setBreakpointsForCurrentProject(filesAndLines) if result: - expectedBreakpointsOrder = [{os.path.join(workingDir, projectName, "main.cpp"):8}, + expectedBreakpointsOrder = [{os.path.join(workingDir, projectName, "main.cpp"):10}, {os.path.join(workingDir, projectName, "main.qml"):13}] availableConfigs = iterateBuildConfigs(len(checkedTargets), "Debug") progressBarWait() From 08aa833825c7ee48a99c763d85905f59b9146b96 Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Fri, 15 Sep 2017 13:30:26 +0200 Subject: [PATCH 08/13] Sort root directories in file system view Change-Id: I8ce68ffa4752c89de735583640103bc22c2a8bc7 Reviewed-by: Tobias Hunger --- .../foldernavigationwidget.cpp | 51 ++++++++++------- .../projectexplorer/foldernavigationwidget.h | 57 ++++++++++--------- src/plugins/projectexplorer/session.cpp | 9 ++- 3 files changed, 66 insertions(+), 51 deletions(-) diff --git a/src/plugins/projectexplorer/foldernavigationwidget.cpp b/src/plugins/projectexplorer/foldernavigationwidget.cpp index 797c0c2b15b..7b6d78366dc 100644 --- a/src/plugins/projectexplorer/foldernavigationwidget.cpp +++ b/src/plugins/projectexplorer/foldernavigationwidget.cpp @@ -53,12 +53,15 @@ #include #include +const int PATH_ROLE = Qt::UserRole; +const int ID_ROLE = Qt::UserRole + 1; + namespace ProjectExplorer { namespace Internal { static FolderNavigationWidgetFactory *m_instance = nullptr; -QVector +QVector FolderNavigationWidgetFactory::m_rootDirectories; // FolderNavigationModel: Shows path as tooltip. @@ -164,21 +167,26 @@ void FolderNavigationWidget::toggleAutoSynchronization() setAutoSynchronization(!m_autoSync); } -void FolderNavigationWidget::addRootDirectory(const QString &displayName, - const Utils::FileName &directory) +void FolderNavigationWidget::addRootDirectory( + const FolderNavigationWidgetFactory::RootDirectory &directory) { - m_rootSelector->addItem(displayName, qVariantFromValue(directory)); - m_rootSelector->setItemData(m_rootSelector->count() - 1, - directory.toUserOutput(), - Qt::ToolTipRole); + // insert sorted + int index = 0; + while (index < m_rootSelector->count() + && m_rootSelector->itemData(index, ID_ROLE).toString() < directory.id) + ++index; + m_rootSelector->insertItem(index, directory.displayName); + m_rootSelector->setItemData(index, qVariantFromValue(directory.path), PATH_ROLE); + m_rootSelector->setItemData(index, directory.id, ID_ROLE); + m_rootSelector->setItemData(index, directory.path.toUserOutput(), Qt::ToolTipRole); if (m_autoSync) // we might find a better root for current selection now setCurrentEditor(Core::EditorManager::currentEditor()); } -void FolderNavigationWidget::removeRootDirectory(const Utils::FileName &directory) +void FolderNavigationWidget::removeRootDirectory(const QString &id) { for (int i = 0; i < m_rootSelector->count(); ++i) { - if (m_rootSelector->itemData(i).value() == directory) { + if (m_rootSelector->itemData(i, ID_ROLE).toString() == id) { m_rootSelector->removeItem(i); break; } @@ -343,14 +351,15 @@ FolderNavigationWidgetFactory::FolderNavigationWidgetFactory() setPriority(400); setId("File System"); setActivationSequence(QKeySequence(Core::UseMacShortcuts ? tr("Meta+Y") : tr("Alt+Y"))); - addRootDirectory(FolderNavigationWidget::tr("Computer"), Utils::FileName()); + addRootDirectory( + {QLatin1String("A.Computer"), FolderNavigationWidget::tr("Computer"), Utils::FileName()}); } Core::NavigationView FolderNavigationWidgetFactory::createWidget() { auto fnw = new FolderNavigationWidget; - for (const DirectoryEntry &root : m_rootDirectories) - fnw->addRootDirectory(root.first, root.second); + for (const RootDirectory &root : m_rootDirectories) + fnw->addRootDirectory(root); connect(this, &FolderNavigationWidgetFactory::rootDirectoryAdded, fnw, @@ -392,21 +401,19 @@ void FolderNavigationWidgetFactory::restoreSettings(QSettings *settings, int pos fnw->setAutoSynchronization(settings->value(baseKey + QLatin1String(".SyncWithEditor"), true).toBool()); } -void FolderNavigationWidgetFactory::addRootDirectory(const QString &displayName, - const Utils::FileName &directory) +void FolderNavigationWidgetFactory::addRootDirectory(const RootDirectory &directory) { - m_rootDirectories.append(DirectoryEntry(displayName, directory)); - emit m_instance->rootDirectoryAdded(displayName, directory); + m_rootDirectories.append(directory); + emit m_instance->rootDirectoryAdded(directory); } -void FolderNavigationWidgetFactory::removeRootDirectory(const Utils::FileName &directory) +void FolderNavigationWidgetFactory::removeRootDirectory(const QString &id) { - const int index = Utils::indexOf(m_rootDirectories, [directory](const DirectoryEntry &entry) { - return entry.second == directory; - }); - QTC_ASSERT(index >= 0, return); + const int index = Utils::indexOf(m_rootDirectories, + [id](const RootDirectory &entry) { return entry.id == id; }); + QTC_ASSERT(index >= 0, return ); m_rootDirectories.removeAt(index); - emit m_instance->rootDirectoryRemoved(directory); + emit m_instance->rootDirectoryRemoved(id); } } // namespace Internal diff --git a/src/plugins/projectexplorer/foldernavigationwidget.h b/src/plugins/projectexplorer/foldernavigationwidget.h index 22f88f43485..7436e23cce9 100644 --- a/src/plugins/projectexplorer/foldernavigationwidget.h +++ b/src/plugins/projectexplorer/foldernavigationwidget.h @@ -26,13 +26,13 @@ #pragma once #include +#include #include namespace Core { class IEditor; } namespace Utils { -class FileName; class NavigationTreeView; } @@ -46,6 +46,34 @@ QT_END_NAMESPACE namespace ProjectExplorer { namespace Internal { +class FolderNavigationWidgetFactory : public Core::INavigationWidgetFactory +{ + Q_OBJECT + +public: + struct RootDirectory { + QString id; + QString displayName; + Utils::FileName path; + }; + + FolderNavigationWidgetFactory(); + + Core::NavigationView createWidget() override; + void saveSettings(QSettings *settings, int position, QWidget *widget) override; + void restoreSettings(QSettings *settings, int position, QWidget *widget) override; + + static void addRootDirectory(const RootDirectory &directory); + static void removeRootDirectory(const QString &id); + +signals: + void rootDirectoryAdded(const RootDirectory &directory); + void rootDirectoryRemoved(const QString &id); + +private: + static QVector m_rootDirectories; +}; + class FolderNavigationWidget : public QWidget { Q_OBJECT @@ -61,8 +89,8 @@ public: void setAutoSynchronization(bool sync); void toggleAutoSynchronization(); - void addRootDirectory(const QString &displayName, const Utils::FileName &directory); - void removeRootDirectory(const Utils::FileName &directory); + void addRootDirectory(const FolderNavigationWidgetFactory::RootDirectory &directory); + void removeRootDirectory(const QString &id); protected: void contextMenuEvent(QContextMenuEvent *ev) override; @@ -86,28 +114,5 @@ private: friend class FolderNavigationWidgetFactory; }; -class FolderNavigationWidgetFactory : public Core::INavigationWidgetFactory -{ - Q_OBJECT - -public: - FolderNavigationWidgetFactory(); - - Core::NavigationView createWidget() override; - void saveSettings(QSettings *settings, int position, QWidget *widget) override; - void restoreSettings(QSettings *settings, int position, QWidget *widget) override; - - static void addRootDirectory(const QString &displayName, const Utils::FileName &directory); - static void removeRootDirectory(const Utils::FileName &directory); - -signals: - void rootDirectoryAdded(const QString &displayName, const Utils::FileName &directory); - void rootDirectoryRemoved(const Utils::FileName &directory); - -private: - using DirectoryEntry = std::pair; - static QVector m_rootDirectories; -}; - } // namespace Internal } // namespace ProjectExplorer diff --git a/src/plugins/projectexplorer/session.cpp b/src/plugins/projectexplorer/session.cpp index 458bc525469..aa85a6dd2f4 100644 --- a/src/plugins/projectexplorer/session.cpp +++ b/src/plugins/projectexplorer/session.cpp @@ -386,8 +386,10 @@ void SessionManager::addProject(Project *pro) m_instance, [pro]() { m_instance->projectDisplayNameChanged(pro); }); emit m_instance->projectAdded(pro); - FolderNavigationWidgetFactory::addRootDirectory(pro->displayName(), - pro->projectFilePath().parentDir()); + FolderNavigationWidgetFactory::addRootDirectory( + {"P." + pro->displayName() + "." + pro->projectFilePath().toString(), + pro->displayName(), + pro->projectFilePath().parentDir()}); configureEditors(pro); connect(pro, &Project::fileListChanged, [pro](){ configureEditors(pro); }); } @@ -742,7 +744,8 @@ void SessionManager::removeProjects(QList remove) m_instance, &SessionManager::clearProjectFileCache); d->m_projectFileCache.remove(pro); emit m_instance->projectRemoved(pro); - FolderNavigationWidgetFactory::removeRootDirectory(pro->projectFilePath().parentDir()); + FolderNavigationWidgetFactory::removeRootDirectory("P." + pro->displayName() + "." + + pro->projectFilePath().toString()); delete pro; } From 716808d9fd4264130eabb2ebb31aa8a1ca5c3349 Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Fri, 15 Sep 2017 13:33:23 +0200 Subject: [PATCH 09/13] Add Home folder to file system view Change-Id: I580475e06dafe835512d078fec30f59d4e798438 Reviewed-by: Tobias Hunger --- src/plugins/projectexplorer/foldernavigationwidget.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/plugins/projectexplorer/foldernavigationwidget.cpp b/src/plugins/projectexplorer/foldernavigationwidget.cpp index 7b6d78366dc..f12547ea481 100644 --- a/src/plugins/projectexplorer/foldernavigationwidget.cpp +++ b/src/plugins/projectexplorer/foldernavigationwidget.cpp @@ -353,6 +353,9 @@ FolderNavigationWidgetFactory::FolderNavigationWidgetFactory() setActivationSequence(QKeySequence(Core::UseMacShortcuts ? tr("Meta+Y") : tr("Alt+Y"))); addRootDirectory( {QLatin1String("A.Computer"), FolderNavigationWidget::tr("Computer"), Utils::FileName()}); + addRootDirectory({QLatin1String("A.Home"), + FolderNavigationWidget::tr("Home"), + Utils::FileName::fromString(QDir::homePath())}); } Core::NavigationView FolderNavigationWidgetFactory::createWidget() From f292a5e45b6c0f5cd55e53dbdc8815ad19458319 Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Mon, 18 Sep 2017 13:39:35 +0200 Subject: [PATCH 10/13] Add projects directory to folder navigation widget Change-Id: Ia925fa99ba0f11be860f214e7809731ddf990268 Reviewed-by: Tobias Hunger --- src/plugins/coreplugin/documentmanager.cpp | 5 +- src/plugins/coreplugin/documentmanager.h | 1 + .../foldernavigationwidget.cpp | 49 ++++++++++++++----- .../projectexplorer/foldernavigationwidget.h | 6 ++- src/plugins/projectexplorer/session.cpp | 2 +- 5 files changed, 47 insertions(+), 16 deletions(-) diff --git a/src/plugins/coreplugin/documentmanager.cpp b/src/plugins/coreplugin/documentmanager.cpp index c4744e75931..afbc8da18a0 100644 --- a/src/plugins/coreplugin/documentmanager.cpp +++ b/src/plugins/coreplugin/documentmanager.cpp @@ -1365,7 +1365,10 @@ FileName DocumentManager::projectsDirectory() void DocumentManager::setProjectsDirectory(const FileName &directory) { - d->m_projectsDirectory = directory; + if (d->m_projectsDirectory != directory) { + d->m_projectsDirectory = directory; + emit m_instance->projectsDirectoryChanged(d->m_projectsDirectory); + } } /*! diff --git a/src/plugins/coreplugin/documentmanager.h b/src/plugins/coreplugin/documentmanager.h index d8a243ea6f6..052a7ee7bd4 100644 --- a/src/plugins/coreplugin/documentmanager.h +++ b/src/plugins/coreplugin/documentmanager.h @@ -146,6 +146,7 @@ signals: void allDocumentsRenamed(const QString &from, const QString &to); /// emitted if one document changed its name e.g. due to save as void documentRenamed(Core::IDocument *document, const QString &from, const QString &to); + void projectsDirectoryChanged(const Utils::FileName &directory); protected: bool eventFilter(QObject *obj, QEvent *e); diff --git a/src/plugins/projectexplorer/foldernavigationwidget.cpp b/src/plugins/projectexplorer/foldernavigationwidget.cpp index f12547ea481..10ed90d4e0a 100644 --- a/src/plugins/projectexplorer/foldernavigationwidget.cpp +++ b/src/plugins/projectexplorer/foldernavigationwidget.cpp @@ -27,6 +27,7 @@ #include "projectexplorer.h" #include +#include #include #include #include @@ -56,6 +57,8 @@ const int PATH_ROLE = Qt::UserRole; const int ID_ROLE = Qt::UserRole + 1; +const char PROJECTSDIRECTORYROOT_ID[] = "A.Projects"; + namespace ProjectExplorer { namespace Internal { @@ -167,7 +170,7 @@ void FolderNavigationWidget::toggleAutoSynchronization() setAutoSynchronization(!m_autoSync); } -void FolderNavigationWidget::addRootDirectory( +void FolderNavigationWidget::insertRootDirectory( const FolderNavigationWidgetFactory::RootDirectory &directory) { // insert sorted @@ -175,10 +178,13 @@ void FolderNavigationWidget::addRootDirectory( while (index < m_rootSelector->count() && m_rootSelector->itemData(index, ID_ROLE).toString() < directory.id) ++index; - m_rootSelector->insertItem(index, directory.displayName); + if (m_rootSelector->itemData(index, ID_ROLE).toString() != directory.id) + m_rootSelector->insertItem(index, directory.displayName); m_rootSelector->setItemData(index, qVariantFromValue(directory.path), PATH_ROLE); m_rootSelector->setItemData(index, directory.id, ID_ROLE); m_rootSelector->setItemData(index, directory.path.toUserOutput(), Qt::ToolTipRole); + if (m_rootSelector->currentIndex() == index) + setRootDirectory(directory.path); if (m_autoSync) // we might find a better root for current selection now setCurrentEditor(Core::EditorManager::currentEditor()); } @@ -351,22 +357,27 @@ FolderNavigationWidgetFactory::FolderNavigationWidgetFactory() setPriority(400); setId("File System"); setActivationSequence(QKeySequence(Core::UseMacShortcuts ? tr("Meta+Y") : tr("Alt+Y"))); - addRootDirectory( + insertRootDirectory( {QLatin1String("A.Computer"), FolderNavigationWidget::tr("Computer"), Utils::FileName()}); - addRootDirectory({QLatin1String("A.Home"), - FolderNavigationWidget::tr("Home"), - Utils::FileName::fromString(QDir::homePath())}); + insertRootDirectory({QLatin1String("A.Home"), + FolderNavigationWidget::tr("Home"), + Utils::FileName::fromString(QDir::homePath())}); + updateProjectsDirectoryRoot(); + connect(Core::DocumentManager::instance(), + &Core::DocumentManager::projectsDirectoryChanged, + this, + &FolderNavigationWidgetFactory::updateProjectsDirectoryRoot); } Core::NavigationView FolderNavigationWidgetFactory::createWidget() { auto fnw = new FolderNavigationWidget; for (const RootDirectory &root : m_rootDirectories) - fnw->addRootDirectory(root); + fnw->insertRootDirectory(root); connect(this, &FolderNavigationWidgetFactory::rootDirectoryAdded, fnw, - &FolderNavigationWidget::addRootDirectory); + &FolderNavigationWidget::insertRootDirectory); connect(this, &FolderNavigationWidgetFactory::rootDirectoryRemoved, fnw, @@ -404,20 +415,34 @@ void FolderNavigationWidgetFactory::restoreSettings(QSettings *settings, int pos fnw->setAutoSynchronization(settings->value(baseKey + QLatin1String(".SyncWithEditor"), true).toBool()); } -void FolderNavigationWidgetFactory::addRootDirectory(const RootDirectory &directory) +void FolderNavigationWidgetFactory::insertRootDirectory(const RootDirectory &directory) { - m_rootDirectories.append(directory); + const int index = rootIndex(directory.id); + if (index < 0) + m_rootDirectories.append(directory); emit m_instance->rootDirectoryAdded(directory); } void FolderNavigationWidgetFactory::removeRootDirectory(const QString &id) { - const int index = Utils::indexOf(m_rootDirectories, - [id](const RootDirectory &entry) { return entry.id == id; }); + const int index = rootIndex(id); QTC_ASSERT(index >= 0, return ); m_rootDirectories.removeAt(index); emit m_instance->rootDirectoryRemoved(id); } +int FolderNavigationWidgetFactory::rootIndex(const QString &id) +{ + return Utils::indexOf(m_rootDirectories, + [id](const RootDirectory &entry) { return entry.id == id; }); +} + +void FolderNavigationWidgetFactory::updateProjectsDirectoryRoot() +{ + insertRootDirectory({QLatin1String(PROJECTSDIRECTORYROOT_ID), + FolderNavigationWidget::tr("Projects"), + Core::DocumentManager::projectsDirectory()}); +} + } // namespace Internal } // namespace ProjectExplorer diff --git a/src/plugins/projectexplorer/foldernavigationwidget.h b/src/plugins/projectexplorer/foldernavigationwidget.h index 7436e23cce9..06c91c17185 100644 --- a/src/plugins/projectexplorer/foldernavigationwidget.h +++ b/src/plugins/projectexplorer/foldernavigationwidget.h @@ -63,7 +63,7 @@ public: void saveSettings(QSettings *settings, int position, QWidget *widget) override; void restoreSettings(QSettings *settings, int position, QWidget *widget) override; - static void addRootDirectory(const RootDirectory &directory); + static void insertRootDirectory(const RootDirectory &directory); static void removeRootDirectory(const QString &id); signals: @@ -71,6 +71,8 @@ signals: void rootDirectoryRemoved(const QString &id); private: + static int rootIndex(const QString &id); + void updateProjectsDirectoryRoot(); static QVector m_rootDirectories; }; @@ -89,7 +91,7 @@ public: void setAutoSynchronization(bool sync); void toggleAutoSynchronization(); - void addRootDirectory(const FolderNavigationWidgetFactory::RootDirectory &directory); + void insertRootDirectory(const FolderNavigationWidgetFactory::RootDirectory &directory); void removeRootDirectory(const QString &id); protected: diff --git a/src/plugins/projectexplorer/session.cpp b/src/plugins/projectexplorer/session.cpp index aa85a6dd2f4..636820e56e2 100644 --- a/src/plugins/projectexplorer/session.cpp +++ b/src/plugins/projectexplorer/session.cpp @@ -386,7 +386,7 @@ void SessionManager::addProject(Project *pro) m_instance, [pro]() { m_instance->projectDisplayNameChanged(pro); }); emit m_instance->projectAdded(pro); - FolderNavigationWidgetFactory::addRootDirectory( + FolderNavigationWidgetFactory::insertRootDirectory( {"P." + pro->displayName() + "." + pro->projectFilePath().toString(), pro->displayName(), pro->projectFilePath().parentDir()}); From f5f4ebff739505a21353a0881252331003b7b410 Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Tue, 26 Sep 2017 10:41:57 +0200 Subject: [PATCH 11/13] Update project names in file system navigation pane When the project reports a change in the display name we need to update the drop down in the file system navigation pane as well. Task-number: QTCREATORBUG-18972 Change-Id: Icfc0e6b2185f147bfc36589d8aea13a0966e8793 Reviewed-by: Tobias Hunger --- src/plugins/projectexplorer/session.cpp | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/plugins/projectexplorer/session.cpp b/src/plugins/projectexplorer/session.cpp index 636820e56e2..cd66c88caea 100644 --- a/src/plugins/projectexplorer/session.cpp +++ b/src/plugins/projectexplorer/session.cpp @@ -118,6 +118,11 @@ private: static SessionManager *m_instance = nullptr; static SessionManagerPrivate *d = nullptr; +static QString projectFolderId(Project *pro) +{ + return "P." + pro->displayName() + "." + pro->projectFilePath().toString(); +} + SessionManager::SessionManager(QObject *parent) : QObject(parent) { m_instance = this; @@ -386,12 +391,14 @@ void SessionManager::addProject(Project *pro) m_instance, [pro]() { m_instance->projectDisplayNameChanged(pro); }); emit m_instance->projectAdded(pro); - FolderNavigationWidgetFactory::insertRootDirectory( - {"P." + pro->displayName() + "." + pro->projectFilePath().toString(), - pro->displayName(), - pro->projectFilePath().parentDir()}); + const auto updateFolderNavigation = [pro] { + FolderNavigationWidgetFactory::insertRootDirectory( + {projectFolderId(pro), pro->displayName(), pro->projectFilePath().parentDir()}); + }; + updateFolderNavigation(); configureEditors(pro); connect(pro, &Project::fileListChanged, [pro](){ configureEditors(pro); }); + connect(pro, &Project::displayNameChanged, pro, updateFolderNavigation); } void SessionManager::removeProject(Project *project) @@ -744,8 +751,7 @@ void SessionManager::removeProjects(QList remove) m_instance, &SessionManager::clearProjectFileCache); d->m_projectFileCache.remove(pro); emit m_instance->projectRemoved(pro); - FolderNavigationWidgetFactory::removeRootDirectory("P." + pro->displayName() + "." - + pro->projectFilePath().toString()); + FolderNavigationWidgetFactory::removeRootDirectory(projectFolderId(pro)); delete pro; } From 8e1af07c11c3bfa891703eff6a41ec4a5f291264 Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Tue, 26 Sep 2017 12:38:38 +0200 Subject: [PATCH 12/13] QmlDesigner: Add option in navigator to show only visible items At the moment we show everything in default properties including non visible items. This is a bad default. Instead we provide an option if only visible items or all objects are shown in the navigator. Change-Id: I65b58d949136bcce4b06f1f47f56fb0f210fed5c Reviewed-by: Tim Jenssen --- .../navigator/navigatormodelinterface.h | 2 + .../navigator/navigatortreemodel.cpp | 29 ++++++++- .../components/navigator/navigatortreemodel.h | 3 + .../components/navigator/navigatorview.cpp | 12 ++++ .../components/navigator/navigatorview.h | 1 + .../components/navigator/navigatorwidget.cpp | 63 +++++++++++++------ .../components/navigator/navigatorwidget.h | 1 + src/plugins/qmldesigner/designersettings.cpp | 1 + src/plugins/qmldesigner/designersettings.h | 1 + 9 files changed, 90 insertions(+), 23 deletions(-) diff --git a/src/plugins/qmldesigner/components/navigator/navigatormodelinterface.h b/src/plugins/qmldesigner/components/navigator/navigatormodelinterface.h index 243aa489cf0..bedcc2f561a 100644 --- a/src/plugins/qmldesigner/components/navigator/navigatormodelinterface.h +++ b/src/plugins/qmldesigner/components/navigator/navigatormodelinterface.h @@ -43,6 +43,8 @@ public: virtual void notifyModelNodesRemoved(const QList &modelNodes) = 0; virtual void notifyModelNodesInserted(const QList &modelNodes) = 0; virtual void notifyModelNodesMoved(const QList &modelNodes) = 0; + virtual void setFilter(bool showObjects) = 0; + virtual void resetModel() = 0; }; } //QmlDesigner diff --git a/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp b/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp index 0b6c3cc6ae8..3b78b09de1f 100644 --- a/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp +++ b/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp @@ -246,6 +246,16 @@ Qt::ItemFlags NavigatorTreeModel::flags(const QModelIndex &index) const | Qt::ItemNeverHasChildren; } +QList filteredList(const NodeListProperty &property, bool filter) +{ + if (!filter) + return property.toModelNodeList(); + + return Utils::filtered(property.toModelNodeList(), [] (const ModelNode &arg) { + return QmlItemNode::isValidQmlItemNode(arg); + }); +} + QModelIndex NavigatorTreeModel::index(int row, int column, const QModelIndex &parent) const { @@ -262,7 +272,7 @@ QModelIndex NavigatorTreeModel::index(int row, int column, ModelNode modelNode; if (parentModelNode.defaultNodeListProperty().isValid()) - modelNode = parentModelNode.defaultNodeListProperty().at(row); + modelNode = filteredList(parentModelNode.defaultNodeListProperty(), m_showOnlyVisibleItems).at(row); if (!modelNode.isValid()) return QModelIndex(); @@ -293,7 +303,7 @@ QModelIndex NavigatorTreeModel::parent(const QModelIndex &index) const int row = 0; if (!parentModelNode.isRootNode() && parentModelNode.parentProperty().isNodeListProperty()) - row = parentModelNode.parentProperty().toNodeListProperty().indexOf(parentModelNode); + row = filteredList(parentModelNode.parentProperty().toNodeListProperty(), m_showOnlyVisibleItems).indexOf(parentModelNode); return createIndexFromModelNode(row, 0, parentModelNode); } @@ -313,7 +323,7 @@ int NavigatorTreeModel::rowCount(const QModelIndex &parent) const int rows = 0; if (modelNode.defaultNodeListProperty().isValid()) - rows = modelNode.defaultNodeListProperty().count(); + rows = filteredList(modelNode.defaultNodeListProperty(), m_showOnlyVisibleItems).count(); return rows; } @@ -628,4 +638,17 @@ void NavigatorTreeModel::notifyModelNodesMoved(const QList &modelNode layoutChanged(indexes); } +void NavigatorTreeModel::setFilter(bool showOnlyVisibleItems) +{ + m_showOnlyVisibleItems = showOnlyVisibleItems; + resetModel(); +} + +void NavigatorTreeModel::resetModel() +{ + beginResetModel(); + m_nodeIndexHash.clear(); + endResetModel(); +} + } // QmlDesigner diff --git a/src/plugins/qmldesigner/components/navigator/navigatortreemodel.h b/src/plugins/qmldesigner/components/navigator/navigatortreemodel.h index 9b6e22b114a..92b352fce50 100644 --- a/src/plugins/qmldesigner/components/navigator/navigatortreemodel.h +++ b/src/plugins/qmldesigner/components/navigator/navigatortreemodel.h @@ -87,6 +87,8 @@ public: void notifyModelNodesRemoved(const QList &modelNodes) override; void notifyModelNodesInserted(const QList &modelNodes) override; void notifyModelNodesMoved(const QList &modelNodes) override; + void setFilter(bool showOnlyVisibleItems) override; + void resetModel() override; private: void moveNodesInteractive(NodeAbstractProperty &parentProperty, const QList &modelNodes, int targetIndex); @@ -97,6 +99,7 @@ private: QPointer m_view; mutable QHash m_nodeIndexHash; + bool m_showOnlyVisibleItems = true; }; } // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/navigator/navigatorview.cpp b/src/plugins/qmldesigner/components/navigator/navigatorview.cpp index 4bf00a00e7b..48531cf82eb 100644 --- a/src/plugins/qmldesigner/components/navigator/navigatorview.cpp +++ b/src/plugins/qmldesigner/components/navigator/navigatorview.cpp @@ -34,6 +34,7 @@ #include #include +#include #include #include #include @@ -88,6 +89,7 @@ NavigatorView::NavigatorView(QObject* parent) : connect(m_widget.data(), &NavigatorWidget::rightButtonClicked, this, &NavigatorView::rightButtonClicked); connect(m_widget.data(), &NavigatorWidget::downButtonClicked, this, &NavigatorView::downButtonClicked); connect(m_widget.data(), &NavigatorWidget::upButtonClicked, this, &NavigatorView::upButtonClicked); + connect(m_widget.data(), &NavigatorWidget::filterToggled, this, &NavigatorView::filterToggled); #ifndef QMLDESIGNER_TEST NameItemDelegate *idDelegate = new NameItemDelegate(this); @@ -145,6 +147,9 @@ void NavigatorView::modelAttached(Model *model) { AbstractView::modelAttached(model); + m_currentModelInterface->setFilter( + DesignerSettings::getValue(DesignerSettingsKey::NAVIGATOR_SHOW_ONLY_VISIBLE_ITEMS).toBool()); + QTreeView *treeView = treeWidget(); treeView->expandAll(); @@ -400,6 +405,13 @@ void NavigatorView::downButtonClicked() blockSelectionChangedSignal(blocked); } +void NavigatorView::filterToggled(bool flag) +{ + m_currentModelInterface->setFilter(flag); + treeWidget()->expandAll(); + DesignerSettings::setValue(DesignerSettingsKey::NAVIGATOR_SHOW_ONLY_VISIBLE_ITEMS, flag); +} + void NavigatorView::changeSelection(const QItemSelection & /*newSelection*/, const QItemSelection &/*deselected*/) { if (m_blockSelectionChangedSignal) diff --git a/src/plugins/qmldesigner/components/navigator/navigatorview.h b/src/plugins/qmldesigner/components/navigator/navigatorview.h index 24c65f2eeb8..d02a0d38fe0 100644 --- a/src/plugins/qmldesigner/components/navigator/navigatorview.h +++ b/src/plugins/qmldesigner/components/navigator/navigatorview.h @@ -99,6 +99,7 @@ private: void rightButtonClicked(); void upButtonClicked(); void downButtonClicked(); + void filterToggled(bool); protected: //functions QTreeView *treeWidget() const; diff --git a/src/plugins/qmldesigner/components/navigator/navigatorwidget.cpp b/src/plugins/qmldesigner/components/navigator/navigatorwidget.cpp index d9794f6388e..0785e704df2 100644 --- a/src/plugins/qmldesigner/components/navigator/navigatorwidget.cpp +++ b/src/plugins/qmldesigner/components/navigator/navigatorwidget.cpp @@ -27,14 +27,17 @@ #include "navigatorview.h" #include "qmldesignerconstants.h" #include "qmldesignericons.h" +#include #include #include #include #include +#include #include #include #include +#include namespace QmlDesigner { @@ -80,29 +83,49 @@ QList NavigatorWidget::createToolBarWidgets() { QList buttons; - buttons.append(new QToolButton()); - buttons.last()->setIcon(Icons::ARROW_LEFT.icon()); - buttons.last()->setToolTip(tr("Become last sibling of parent (CTRL + Left).")); - buttons.last()->setShortcut(QKeySequence(Qt::Key_Left | Qt::CTRL)); - connect(buttons.last(), &QAbstractButton::clicked, this, &NavigatorWidget::leftButtonClicked); - buttons.append(new QToolButton()); - buttons.last()->setIcon(Icons::ARROW_RIGHT.icon()); - buttons.last()->setToolTip(tr("Become child of last sibling (CTRL + Right).")); - buttons.last()->setShortcut(QKeySequence(Qt::Key_Right | Qt::CTRL)); - connect(buttons.last(), &QAbstractButton::clicked, this, &NavigatorWidget::rightButtonClicked); + auto button = new QToolButton(); + button->setIcon(Icons::ARROW_LEFT.icon()); + button->setToolTip(tr("Become last sibling of parent (CTRL + Left).")); + button->setShortcut(QKeySequence(Qt::Key_Left | Qt::CTRL)); + connect(button, &QAbstractButton::clicked, this, &NavigatorWidget::leftButtonClicked); + buttons.append(button); - buttons.append(new QToolButton()); - buttons.last()->setIcon(Icons::ARROW_DOWN.icon()); - buttons.last()->setToolTip(tr("Move down (CTRL + Down).")); - buttons.last()->setShortcut(QKeySequence(Qt::Key_Down | Qt::CTRL)); - connect(buttons.last(), &QAbstractButton::clicked, this, &NavigatorWidget::downButtonClicked); + button = new QToolButton(); + button->setIcon(Icons::ARROW_RIGHT.icon()); + button->setToolTip(tr("Become child of last sibling (CTRL + Right).")); + button->setShortcut(QKeySequence(Qt::Key_Right | Qt::CTRL)); + connect(button, &QAbstractButton::clicked, this, &NavigatorWidget::rightButtonClicked); + buttons.append(button); - buttons.append(new QToolButton()); - buttons.last()->setIcon(Icons::ARROW_UP.icon()); - buttons.last()->setToolTip(tr("Move up (CTRL + Up).")); - buttons.last()->setShortcut(QKeySequence(Qt::Key_Up | Qt::CTRL)); - connect(buttons.last(), &QAbstractButton::clicked, this, &NavigatorWidget::upButtonClicked); + button = new QToolButton(); + button->setIcon(Icons::ARROW_DOWN.icon()); + button->setToolTip(tr("Move down (CTRL + Down).")); + button->setShortcut(QKeySequence(Qt::Key_Down | Qt::CTRL)); + connect(button, &QAbstractButton::clicked, this, &NavigatorWidget::downButtonClicked); + buttons.append(button); + + button = new QToolButton(); + button->setIcon(Icons::ARROW_UP.icon()); + button->setToolTip(tr("Move up (CTRL + Up).")); + button->setShortcut(QKeySequence(Qt::Key_Up | Qt::CTRL)); + connect(button, &QAbstractButton::clicked, this, &NavigatorWidget::upButtonClicked); + buttons.append(button); + + auto filter = new QToolButton; + filter->setIcon(Utils::Icons::FILTER.icon()); + filter->setToolTip(tr("Filter Tree")); + filter->setPopupMode(QToolButton::InstantPopup); + filter->setProperty("noArrow", true); + auto filterMenu = new QMenu(filter); + auto objectAction = new QAction(tr("Show only visible itmes.")); + objectAction->setCheckable(true); + objectAction->setChecked( + DesignerSettings::getValue(DesignerSettingsKey::NAVIGATOR_SHOW_ONLY_VISIBLE_ITEMS).toBool()); + connect(objectAction, &QAction::toggled, this, &NavigatorWidget::filterToggled); + filterMenu->addAction(objectAction); + filter->setMenu(filterMenu); + buttons.append(filter); return buttons; } diff --git a/src/plugins/qmldesigner/components/navigator/navigatorwidget.h b/src/plugins/qmldesigner/components/navigator/navigatorwidget.h index 526004cf840..45e8b19c9b5 100644 --- a/src/plugins/qmldesigner/components/navigator/navigatorwidget.h +++ b/src/plugins/qmldesigner/components/navigator/navigatorwidget.h @@ -53,6 +53,7 @@ signals: void rightButtonClicked(); void upButtonClicked(); void downButtonClicked(); + void filterToggled(bool); private: // functions NavigatorView *navigatorView() const; diff --git a/src/plugins/qmldesigner/designersettings.cpp b/src/plugins/qmldesigner/designersettings.cpp index c75c98c80bc..026fb51bcfb 100644 --- a/src/plugins/qmldesigner/designersettings.cpp +++ b/src/plugins/qmldesigner/designersettings.cpp @@ -74,6 +74,7 @@ void DesignerSettings::fromSettings(QSettings *settings) restoreValue(settings, DesignerSettingsKey::FORWARD_PUPPET_OUTPUT, QString()); restoreValue(settings, DesignerSettingsKey::REFORMAT_UI_QML_FILES, true); restoreValue(settings, DesignerSettingsKey::IGNORE_DEVICE_PIXEL_RATIO, false); + restoreValue(settings, DesignerSettingsKey::NAVIGATOR_SHOW_ONLY_VISIBLE_ITEMS, true); settings->endGroup(); settings->endGroup(); diff --git a/src/plugins/qmldesigner/designersettings.h b/src/plugins/qmldesigner/designersettings.h index a3710d278dc..7172c10491e 100644 --- a/src/plugins/qmldesigner/designersettings.h +++ b/src/plugins/qmldesigner/designersettings.h @@ -60,6 +60,7 @@ const char PUPPET_KILL_TIMEOUT[] = "PuppetKillTimeout"; const char DEBUG_PUPPET[] = "DebugPuppet"; const char FORWARD_PUPPET_OUTPUT[] = "ForwardPuppetOutput"; const char STATESEDITOR_EXPANDED[] = "StatesEditorExpanded"; +const char NAVIGATOR_SHOW_ONLY_VISIBLE_ITEMS[] = "NavigatorShowOnlyVisibleItems"; const char REFORMAT_UI_QML_FILES[] = "ReformatUiQmlFiles"; /* These settings are not exposed in ui. */ const char IGNORE_DEVICE_PIXEL_RATIO[] = "IgnoreDevicePixelRaio"; /* The settings can be used to turn off the feature, if there are serious issues */ } From 272645d7907c5b506c89770f0479ce6e4f781443 Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Tue, 26 Sep 2017 12:39:01 +0200 Subject: [PATCH 13/13] QmlDesigner: Add default for DesignerSettingsKey::STATESEDITOR_EXPANDED Change-Id: Iace28338f1cd67d0adb5bc0f573028f9fa030b38 Reviewed-by: Thomas Hartmann --- src/plugins/qmldesigner/designersettings.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/qmldesigner/designersettings.cpp b/src/plugins/qmldesigner/designersettings.cpp index 026fb51bcfb..ec7d1397283 100644 --- a/src/plugins/qmldesigner/designersettings.cpp +++ b/src/plugins/qmldesigner/designersettings.cpp @@ -74,6 +74,7 @@ void DesignerSettings::fromSettings(QSettings *settings) restoreValue(settings, DesignerSettingsKey::FORWARD_PUPPET_OUTPUT, QString()); restoreValue(settings, DesignerSettingsKey::REFORMAT_UI_QML_FILES, true); restoreValue(settings, DesignerSettingsKey::IGNORE_DEVICE_PIXEL_RATIO, false); + restoreValue(settings, DesignerSettingsKey::STATESEDITOR_EXPANDED, false); restoreValue(settings, DesignerSettingsKey::NAVIGATOR_SHOW_ONLY_VISIBLE_ITEMS, true); settings->endGroup();