diff options
Diffstat (limited to 'src/plugins')
36 files changed, 225 insertions, 90 deletions
diff --git a/src/plugins/autotest/autotestplugin.cpp b/src/plugins/autotest/autotestplugin.cpp index 571af4ba08..3d00400ccd 100644 --- a/src/plugins/autotest/autotestplugin.cpp +++ b/src/plugins/autotest/autotestplugin.cpp @@ -46,8 +46,8 @@ #include <coreplugin/actionmanager/command.h> #include <coreplugin/actionmanager/actioncontainer.h> #include <coreplugin/coreconstants.h> - #include <extensionsystem/pluginmanager.h> +#include <projectexplorer/buildmanager.h> #include <QAction> #include <QMessageBox> @@ -102,6 +102,7 @@ void AutotestPlugin::initializeMenuEntries() command->setDefaultKeySequence(QKeySequence(tr("Alt+Shift+T,Alt+A"))); connect(action, &QAction::triggered, this, &AutotestPlugin::onRunAllTriggered); + action->setEnabled(false); menu->addAction(command); action = new QAction(tr("&Run Selected Tests"), this); @@ -109,6 +110,7 @@ void AutotestPlugin::initializeMenuEntries() command->setDefaultKeySequence(QKeySequence(tr("Alt+Shift+T,Alt+R"))); connect(action, &QAction::triggered, this, &AutotestPlugin::onRunSelectedTriggered); + action->setEnabled(false); menu->addAction(command); action = new QAction(tr("Re&scan Tests"), this); @@ -121,7 +123,12 @@ void AutotestPlugin::initializeMenuEntries() ActionContainer *toolsMenu = ActionManager::actionContainer(Core::Constants::M_TOOLS); toolsMenu->addMenu(menu); - connect(toolsMenu->menu(), &QMenu::aboutToShow, + using namespace ProjectExplorer; + connect(BuildManager::instance(), &BuildManager::buildStateChanged, + this, &AutotestPlugin::updateMenuItemsEnabledState); + connect(BuildManager::instance(), &BuildManager::buildQueueFinished, + this, &AutotestPlugin::updateMenuItemsEnabledState); + connect(TestTreeModel::instance(), &TestTreeModel::testTreeModelChanged, this, &AutotestPlugin::updateMenuItemsEnabledState); } @@ -176,7 +183,8 @@ void AutotestPlugin::onRunSelectedTriggered() void AutotestPlugin::updateMenuItemsEnabledState() { - const bool enabled = !TestRunner::instance()->isTestRunning() + const bool enabled = !ProjectExplorer::BuildManager::isBuilding() + && !TestRunner::instance()->isTestRunning() && TestTreeModel::instance()->parser()->state() == TestCodeParser::Idle; const bool hasTests = TestTreeModel::instance()->hasTests(); diff --git a/src/plugins/autotest/autotestplugin.h b/src/plugins/autotest/autotestplugin.h index 8164efb21f..7c3f0712d4 100644 --- a/src/plugins/autotest/autotestplugin.h +++ b/src/plugins/autotest/autotestplugin.h @@ -60,7 +60,7 @@ private: void updateMenuItemsEnabledState(); QList<QObject *> createTestObjects() const override; const QSharedPointer<TestSettings> m_settings; - TestFrameworkManager *m_frameworkManager = 0; + TestFrameworkManager *m_frameworkManager = nullptr; }; } // namespace Internal diff --git a/src/plugins/autotest/gtest/gtesttreeitem.cpp b/src/plugins/autotest/gtest/gtesttreeitem.cpp index a57d44f358..5550e57642 100644 --- a/src/plugins/autotest/gtest/gtesttreeitem.cpp +++ b/src/plugins/autotest/gtest/gtesttreeitem.cpp @@ -104,6 +104,8 @@ TestConfiguration *GTestTreeItem::testConfiguration() const default: return nullptr; } + if (config) + config->setInternalTargets(internalTargets()); return config; } @@ -124,6 +126,7 @@ QList<TestConfiguration *> GTestTreeItem::getAllTestConfigurations() const return result; QHash<QString, int> proFilesWithTestSets; + QHash<QString, QSet<QString> > proFilesWithInternalTargets; for (int row = 0, count = childCount(); row < count; ++row) { const GTestTreeItem *child = static_cast<const GTestTreeItem *>(childItem(row)); @@ -132,6 +135,7 @@ QList<TestConfiguration *> GTestTreeItem::getAllTestConfigurations() const const TestTreeItem *grandChild = child->childItem(grandChildRow); const QString &key = grandChild->proFile(); proFilesWithTestSets.insert(key, proFilesWithTestSets[key] + 1); + proFilesWithInternalTargets.insert(key, grandChild->internalTargets()); } } @@ -142,6 +146,7 @@ QList<TestConfiguration *> GTestTreeItem::getAllTestConfigurations() const tc->setTestCaseCount(it.value()); tc->setProjectFile(it.key()); tc->setProject(project); + tc->setInternalTargets(proFilesWithInternalTargets.value(it.key())); result << tc; } @@ -162,6 +167,7 @@ QList<TestConfiguration *> GTestTreeItem::getSelectedTestConfigurations() const return result; QHash<QString, TestCases> proFilesWithCheckedTestSets; + QHash<QString, QSet<QString> > proFilesWithInternalTargets; for (int row = 0, count = childCount(); row < count; ++row) { const GTestTreeItem *child = static_cast<const GTestTreeItem *>(childItem(row)); @@ -175,6 +181,8 @@ QList<TestConfiguration *> GTestTreeItem::getSelectedTestConfigurations() const auto &testCases = proFilesWithCheckedTestSets[child->childItem(0)->proFile()]; testCases.filters.append(gtestFilter(child->state()).arg(child->name()).arg('*')); testCases.additionalTestCaseCount += grandChildCount - 1; + proFilesWithInternalTargets.insert(child->childItem(0)->proFile(), + child->internalTargets()); break; } case Qt::PartiallyChecked: { @@ -183,6 +191,8 @@ QList<TestConfiguration *> GTestTreeItem::getSelectedTestConfigurations() const if (grandChild->checked() == Qt::Checked) { proFilesWithCheckedTestSets[grandChild->proFile()].filters.append( gtestFilter(child->state()).arg(child->name()).arg(grandChild->name())); + proFilesWithInternalTargets.insert(grandChild->proFile(), + grandChild->internalTargets()); } } break; @@ -198,6 +208,7 @@ QList<TestConfiguration *> GTestTreeItem::getSelectedTestConfigurations() const tc->setTestCaseCount(tc->testCaseCount() + it.value().additionalTestCaseCount); tc->setProjectFile(it.key()); tc->setProject(project); + tc->setInternalTargets(proFilesWithInternalTargets[it.key()]); result << tc; } diff --git a/src/plugins/autotest/qtest/qttesttreeitem.cpp b/src/plugins/autotest/qtest/qttesttreeitem.cpp index def491c196..2b4ad6d6c2 100644 --- a/src/plugins/autotest/qtest/qttesttreeitem.cpp +++ b/src/plugins/autotest/qtest/qttesttreeitem.cpp @@ -134,6 +134,8 @@ TestConfiguration *QtTestTreeItem::testConfiguration() const default: return nullptr; } + if (config) + config->setInternalTargets(internalTargets()); return config; } @@ -160,6 +162,7 @@ QList<TestConfiguration *> QtTestTreeItem::getAllTestConfigurations() const tc->setTestCaseCount(child->childCount()); tc->setProjectFile(child->proFile()); tc->setProject(project); + tc->setInternalTargets(child->internalTargets()); result << tc; } return result; @@ -185,6 +188,7 @@ QList<TestConfiguration *> QtTestTreeItem::getSelectedTestConfigurations() const testConfiguration->setTestCaseCount(child->childCount()); testConfiguration->setProjectFile(child->proFile()); testConfiguration->setProject(project); + testConfiguration->setInternalTargets(child->internalTargets()); result << testConfiguration; continue; case Qt::PartiallyChecked: @@ -210,6 +214,7 @@ QList<TestConfiguration *> QtTestTreeItem::getSelectedTestConfigurations() const testConfiguration->setTestCases(testCases); testConfiguration->setProjectFile(child->proFile()); testConfiguration->setProject(project); + testConfiguration->setInternalTargets(child->internalTargets()); result << testConfiguration; } } diff --git a/src/plugins/autotest/quick/quicktestparser.cpp b/src/plugins/autotest/quick/quicktestparser.cpp index b7528f414c..0d897fe04e 100644 --- a/src/plugins/autotest/quick/quicktestparser.cpp +++ b/src/plugins/autotest/quick/quicktestparser.cpp @@ -36,6 +36,7 @@ #include <qmljs/qmljsdialect.h> #include <qmljstools/qmljsmodelmanager.h> #include <utils/hostosinfo.h> +#include <utils/algorithm.h> #include <utils/qtcassert.h> namespace Autotest { @@ -238,6 +239,49 @@ bool QuickTestParser::handleQtQuickTest(QFutureInterface<TestParseResultPtr> fut return result; } +static QMap<QString, QDateTime> qmlFilesWithMTime(const QString &directory) +{ + const QFileInfoList &qmlFiles = QDir(directory).entryInfoList({ "*.qml" }, + QDir::Files, QDir::Name); + QMap<QString, QDateTime> filesAndDates; + for (const QFileInfo &info : qmlFiles) + filesAndDates.insert(info.fileName(), info.lastModified()); + return filesAndDates; +} + +void QuickTestParser::handleDirectoryChanged(const QString &directory) +{ + const QMap<QString, QDateTime> &filesAndDates = qmlFilesWithMTime(directory); + const QMap<QString, QDateTime> &watched = m_watchedFiles.value(directory); + const QStringList &keys = watched.keys(); + if (filesAndDates.keys() != keys) { // removed or added files + m_watchedFiles[directory] = filesAndDates; + TestTreeModel::instance()->parser()->emitUpdateTestTree(this); + } else { // we might still have different timestamps + const bool timestampChanged = Utils::anyOf(keys, [&](const QString &file) { + return filesAndDates.value(file) != watched.value(file); + }); + if (timestampChanged) { + QmlJS::PathsAndLanguages paths; + paths.maybeInsert(Utils::FileName::fromString(directory), QmlJS::Dialect::Qml); + QFutureInterface<void> future; + QmlJS::ModelManagerInterface *qmlJsMM = QmlJS::ModelManagerInterface::instance(); + QmlJS::ModelManagerInterface::importScan(future, qmlJsMM->workingCopy(), paths, qmlJsMM, + true /*emitDocumentChanges*/, + false /*onlyTheLib*/, + true /*forceRescan*/ ); + } + } +} + +void QuickTestParser::doUpdateWatchPaths(const QStringList &directories) +{ + for (const QString &dir : directories) { + m_directoryWatcher.addPath(dir); + m_watchedFiles[dir] = qmlFilesWithMTime(dir); + } +} + QuickTestParser::QuickTestParser() : CppParser() { @@ -246,11 +290,12 @@ QuickTestParser::QuickTestParser() const QStringList &dirs = m_directoryWatcher.directories(); if (!dirs.isEmpty()) m_directoryWatcher.removePaths(dirs); + m_watchedFiles.clear(); }); connect(&m_directoryWatcher, &QFileSystemWatcher::directoryChanged, - [this] { TestTreeModel::instance()->parser()->emitUpdateTestTree(this); }); + this, &QuickTestParser::handleDirectoryChanged); connect(this, &QuickTestParser::updateWatchPaths, - &m_directoryWatcher, &QFileSystemWatcher::addPaths, Qt::QueuedConnection); + this, &QuickTestParser::doUpdateWatchPaths, Qt::QueuedConnection); } QuickTestParser::~QuickTestParser() diff --git a/src/plugins/autotest/quick/quicktestparser.h b/src/plugins/autotest/quick/quicktestparser.h index 26ba514f2f..2b38efed37 100644 --- a/src/plugins/autotest/quick/quicktestparser.h +++ b/src/plugins/autotest/quick/quicktestparser.h @@ -56,10 +56,13 @@ signals: private: bool handleQtQuickTest(QFutureInterface<TestParseResultPtr> futureInterface, CPlusPlus::Document::Ptr document, const Core::Id &id) const; + void handleDirectoryChanged(const QString &directory); + void doUpdateWatchPaths(const QStringList &directories); QList<QmlJS::Document::Ptr> scanDirectoryForQuickTestQmlFiles(const QString &srcDir) const; QmlJS::Snapshot m_qmlSnapshot; QHash<QString, QString> m_proFilesForQmlFiles; QFileSystemWatcher m_directoryWatcher; + QMap<QString, QMap<QString, QDateTime> > m_watchedFiles; }; } // namespace Internal diff --git a/src/plugins/autotest/quick/quicktesttreeitem.cpp b/src/plugins/autotest/quick/quicktesttreeitem.cpp index d6cd78b82a..5576f97b09 100644 --- a/src/plugins/autotest/quick/quicktesttreeitem.cpp +++ b/src/plugins/autotest/quick/quicktesttreeitem.cpp @@ -27,6 +27,7 @@ #include "quicktestconfiguration.h" #include "quicktestparser.h" +#include <cpptools/cppmodelmanager.h> #include <projectexplorer/session.h> #include <utils/qtcassert.h> @@ -138,6 +139,8 @@ TestConfiguration *QuickTestTreeItem::testConfiguration() const default: return nullptr; } + if (config) + config->setInternalTargets(internalTargets()); return config; } @@ -150,6 +153,7 @@ QList<TestConfiguration *> QuickTestTreeItem::getAllTestConfigurations() const return result; QHash<QString, int> foundProFiles; + QHash<QString, QSet<QString> > proFilesWithTargets; for (int row = 0, count = childCount(); row < count; ++row) { const TestTreeItem *child = childItem(row); // unnamed Quick Tests must be handled separately @@ -158,12 +162,14 @@ QList<TestConfiguration *> QuickTestTreeItem::getAllTestConfigurations() const const TestTreeItem *grandChild = child->childItem(childRow); const QString &proFile = grandChild->proFile(); foundProFiles.insert(proFile, foundProFiles[proFile] + 1); + proFilesWithTargets.insert(proFile, grandChild->internalTargets()); } continue; } // named Quick Test const QString &proFile = child->proFile(); foundProFiles.insert(proFile, foundProFiles[proFile] + child->childCount()); + proFilesWithTargets.insert(proFile, child->internalTargets()); } // create TestConfiguration for each project file QHash<QString, int>::ConstIterator it = foundProFiles.begin(); @@ -173,6 +179,7 @@ QList<TestConfiguration *> QuickTestTreeItem::getAllTestConfigurations() const tc->setTestCaseCount(it.value()); tc->setProjectFile(it.key()); tc->setProject(project); + tc->setInternalTargets(proFilesWithTargets[it.key()]); result << tc; } return result; @@ -203,6 +210,7 @@ QList<TestConfiguration *> QuickTestTreeItem::getSelectedTestConfigurations() co tc->setUnnamedOnly(true); tc->setProjectFile(proFile); tc->setProject(project); + tc->setInternalTargets(grandChild->internalTargets()); foundProFiles.insert(proFile, tc); } } @@ -246,6 +254,7 @@ QList<TestConfiguration *> QuickTestTreeItem::getSelectedTestConfigurations() co tc->setTestCases(testFunctions); tc->setProjectFile(child->proFile()); tc->setProject(project); + tc->setInternalTargets(child->internalTargets()); foundProFiles.insert(child->proFile(), tc); } break; @@ -306,6 +315,20 @@ bool QuickTestTreeItem::lessThan(const TestTreeItem *other, TestTreeItem::SortMo return TestTreeItem::lessThan(other, mode); } +QSet<QString> QuickTestTreeItem::internalTargets() const +{ + QSet<QString> result; + const auto cppMM = CppTools::CppModelManager::instance(); + const auto projectInfo = cppMM->projectInfo(ProjectExplorer::SessionManager::startupProject()); + for (const CppTools::ProjectPart::Ptr projectPart : projectInfo.projectParts()) { + if (projectPart->projectFile == proFile()) { + result.insert(projectPart->buildSystemTarget); + break; + } + } + return result; +} + TestTreeItem *QuickTestTreeItem::unnamedQuickTests() const { if (type() != Root) diff --git a/src/plugins/autotest/quick/quicktesttreeitem.h b/src/plugins/autotest/quick/quicktesttreeitem.h index 64f1cf0fb9..a0e860a52c 100644 --- a/src/plugins/autotest/quick/quicktesttreeitem.h +++ b/src/plugins/autotest/quick/quicktesttreeitem.h @@ -45,7 +45,7 @@ public: TestTreeItem *find(const TestParseResult *result) override; bool modify(const TestParseResult *result) override; bool lessThan(const TestTreeItem *other, SortMode mode) const override; - + QSet<QString> internalTargets() const override; private: TestTreeItem *unnamedQuickTests() const; }; diff --git a/src/plugins/autotest/testconfiguration.cpp b/src/plugins/autotest/testconfiguration.cpp index 880c42457a..52723a5b64 100644 --- a/src/plugins/autotest/testconfiguration.cpp +++ b/src/plugins/autotest/testconfiguration.cpp @@ -64,6 +64,7 @@ static bool isLocal(RunConfiguration *runConfiguration) void TestConfiguration::completeTestInformation(int runMode) { QTC_ASSERT(!m_projectFile.isEmpty(), return); + QTC_ASSERT(!m_buildTargets.isEmpty(), return); Project *project = SessionManager::startupProject(); if (!project) @@ -73,23 +74,16 @@ void TestConfiguration::completeTestInformation(int runMode) if (!target) return; - const auto cppMM = CppTools::CppModelManager::instance(); - const QVector<CppTools::ProjectPart::Ptr> projectParts = cppMM->projectInfo(project).projectParts(); - const QVector<CppTools::ProjectPart::Ptr> relevantParts - = Utils::filtered(projectParts, [this] (const CppTools::ProjectPart::Ptr &part) { - return part->selectedForBuilding && part->projectFile == m_projectFile; - }); - const QSet<QString> buildSystemTargets - = Utils::transform<QSet>(relevantParts, [] (const CppTools::ProjectPart::Ptr &part) { - return part->buildSystemTarget; - }); - - const Utils::FileName fn = Utils::FileName::fromString(m_projectFile); + const QSet<QString> buildSystemTargets = m_buildTargets; const BuildTargetInfo targetInfo = Utils::findOrDefault(target->applicationTargets().list, - [&buildSystemTargets, &fn] (const BuildTargetInfo &bti) { - return Utils::anyOf(buildSystemTargets, [&fn, &bti](const QString &b) { - return b == bti.targetName || (b.contains(bti.targetName) && bti.projectFilePath == fn); + [&buildSystemTargets] (const BuildTargetInfo &bti) { + return Utils::anyOf(buildSystemTargets, [&bti](const QString &b) { + const QStringList targWithProjectFile = b.split('|'); + if (targWithProjectFile.size() != 2) // some build targets might miss the project file + return false; + return targWithProjectFile.at(0) == bti.targetName + && targWithProjectFile.at(1).startsWith(bti.projectFilePath.toString()); }); }); const Utils::FileName executable = targetInfo.targetFilePath; // empty if BTI is default created @@ -97,7 +91,8 @@ void TestConfiguration::completeTestInformation(int runMode) if (!isLocal(runConfig)) // TODO add device support continue; - if (buildSystemTargets.contains(runConfig->buildSystemTarget())) { + const QString bst = runConfig->buildSystemTarget() + '|' + m_projectFile; + if (buildSystemTargets.contains(bst)) { Runnable runnable = runConfig->runnable(); if (!runnable.is<StandardRunnable>()) continue; @@ -146,7 +141,7 @@ void TestConfiguration::completeTestInformation(int runMode) } if (m_displayName.isEmpty()) // happens e.g. when guessing the TestConfiguration or error - m_displayName = buildSystemTargets.isEmpty() ? "unknown" : *buildSystemTargets.begin(); + m_displayName = buildSystemTargets.isEmpty() ? "unknown" : (*buildSystemTargets.begin()).split('|').first(); } /** @@ -204,6 +199,11 @@ void TestConfiguration::setProject(Project *project) m_project = project; } +void TestConfiguration::setInternalTargets(const QSet<QString> &targets) +{ + m_buildTargets = targets; +} + QString TestConfiguration::executableFilePath() const { if (m_executableFile.isEmpty()) diff --git a/src/plugins/autotest/testconfiguration.h b/src/plugins/autotest/testconfiguration.h index e220ea2d36..8d62085982 100644 --- a/src/plugins/autotest/testconfiguration.h +++ b/src/plugins/autotest/testconfiguration.h @@ -66,6 +66,7 @@ public: void setDisplayName(const QString &displayName); void setEnvironment(const Utils::Environment &env); void setProject(ProjectExplorer::Project *project); + void setInternalTargets(const QSet<QString> &targets); QStringList testCases() const { return m_testCases; } int testCaseCount() const { return m_testCaseCount; } @@ -97,6 +98,7 @@ private: QPointer<ProjectExplorer::Project> m_project; bool m_guessedConfiguration = false; TestRunConfiguration *m_runConfig = 0; + QSet<QString> m_buildTargets; }; class DebuggableTestConfiguration : public TestConfiguration diff --git a/src/plugins/autotest/testnavigationwidget.cpp b/src/plugins/autotest/testnavigationwidget.cpp index 6323e0d9f0..5e34c666e0 100644 --- a/src/plugins/autotest/testnavigationwidget.cpp +++ b/src/plugins/autotest/testnavigationwidget.cpp @@ -42,6 +42,7 @@ #include <utils/progressindicator.h> #include <utils/utilsicons.h> #include <coreplugin/actionmanager/actionmanager.h> +#include <projectexplorer/buildmanager.h> #include <QAction> #include <QMenu> @@ -113,7 +114,8 @@ TestNavigationWidget::~TestNavigationWidget() void TestNavigationWidget::contextMenuEvent(QContextMenuEvent *event) { - const bool enabled = !TestRunner::instance()->isTestRunning() + const bool enabled = !ProjectExplorer::BuildManager::isBuilding() + && !TestRunner::instance()->isTestRunning() && m_model->parser()->state() == TestCodeParser::Idle; const bool hasTests = m_model->hasTests(); @@ -170,8 +172,6 @@ void TestNavigationWidget::contextMenuEvent(QContextMenuEvent *event) connect(selectAll, &QAction::triggered, m_view, &TestTreeView::selectAll); connect(deselectAll, &QAction::triggered, m_view, &TestTreeView::deselectAll); - runAll->setEnabled(enabled && hasTests); - runSelected->setEnabled(enabled && hasTests); selectAll->setEnabled(enabled && hasTests); deselectAll->setEnabled(enabled && hasTests); rescan->setEnabled(enabled); diff --git a/src/plugins/autotest/testresultspane.cpp b/src/plugins/autotest/testresultspane.cpp index b4fbab9785..41c9e216e6 100644 --- a/src/plugins/autotest/testresultspane.cpp +++ b/src/plugins/autotest/testresultspane.cpp @@ -34,12 +34,14 @@ #include "testcodeparser.h" #include <aggregation/aggregate.h> +#include <coreplugin/actionmanager/actionmanager.h> #include <coreplugin/coreconstants.h> #include <coreplugin/editormanager/editormanager.h> #include <coreplugin/find/basetextfind.h> #include <coreplugin/find/itemviewfind.h> #include <coreplugin/icontext.h> #include <coreplugin/icore.h> +#include <projectexplorer/buildmanager.h> #include <projectexplorer/projectexplorer.h> #include <texteditor/texteditor.h> #include <utils/theme/theme.h> @@ -511,7 +513,9 @@ void TestResultsPane::onTestRunStarted() m_testRunning = true; m_stopTestRun->setEnabled(true); m_runAll->setEnabled(false); + Core::ActionManager::command(Constants::ACTION_RUN_ALL_ID)->action()->setEnabled(false); m_runSelected->setEnabled(false); + Core::ActionManager::command(Constants::ACTION_RUN_SELECTED_ID)->action()->setEnabled(false); m_summaryWidget->setVisible(false); } @@ -519,8 +523,14 @@ void TestResultsPane::onTestRunFinished() { m_testRunning = false; m_stopTestRun->setEnabled(false); - m_runAll->setEnabled(true); - m_runSelected->setEnabled(true); + + const bool runEnabled = !ProjectExplorer::BuildManager::isBuilding() + && TestTreeModel::instance()->hasTests() + && TestTreeModel::instance()->parser()->state() == TestCodeParser::Idle; + m_runAll->setEnabled(runEnabled); // TODO unify Run* actions + Core::ActionManager::command(Constants::ACTION_RUN_ALL_ID)->action()->setEnabled(runEnabled); + m_runSelected->setEnabled(runEnabled); + Core::ActionManager::command(Constants::ACTION_RUN_SELECTED_ID)->action()->setEnabled(runEnabled); updateSummaryLabel(); m_summaryWidget->setVisible(true); m_model->removeCurrentTestMessage(); @@ -541,6 +551,7 @@ void TestResultsPane::updateRunActions() QString whyNot; TestTreeModel *model = TestTreeModel::instance(); const bool enable = !m_testRunning && !model->parser()->isParsing() && model->hasTests() + && !ProjectExplorer::BuildManager::isBuilding() && ProjectExplorer::ProjectExplorerPlugin::canRunStartupProject( ProjectExplorer::Constants::NORMAL_RUN_MODE, &whyNot); m_runAll->setEnabled(enable); diff --git a/src/plugins/autotest/testtreeitem.cpp b/src/plugins/autotest/testtreeitem.cpp index 9d69a6e50d..7f1992ae58 100644 --- a/src/plugins/autotest/testtreeitem.cpp +++ b/src/plugins/autotest/testtreeitem.cpp @@ -29,6 +29,7 @@ #include "testtreeitem.h" #include <cplusplus/Icons.h> +#include <cpptools/cppmodelmanager.h> #include <texteditor/texteditor.h> #include <QIcon> @@ -281,6 +282,16 @@ bool TestTreeItem::lessThan(const TestTreeItem *other, SortMode mode) const } } +QSet<QString> TestTreeItem::internalTargets() const +{ + auto cppMM = CppTools::CppModelManager::instance(); + const QList<CppTools::ProjectPart::Ptr> projectParts = cppMM->projectPart(filePath()); + QSet<QString> targets; + for (const CppTools::ProjectPart::Ptr part : projectParts) + targets.insert(part->buildSystemTarget); + return targets; +} + void TestTreeItem::revalidateCheckState() { const Type ttiType = type(); diff --git a/src/plugins/autotest/testtreeitem.h b/src/plugins/autotest/testtreeitem.h index 1c5c3f95a1..530a105e27 100644 --- a/src/plugins/autotest/testtreeitem.h +++ b/src/plugins/autotest/testtreeitem.h @@ -110,6 +110,7 @@ public: virtual TestTreeItem *find(const TestParseResult *result) = 0; virtual bool modify(const TestParseResult *result) = 0; + virtual QSet<QString> internalTargets() const; protected: typedef std::function<bool(const TestTreeItem *)> CompareFunction; TestTreeItem *findChildBy(CompareFunction compare) const; diff --git a/src/plugins/autotoolsprojectmanager/autotoolsproject.cpp b/src/plugins/autotoolsprojectmanager/autotoolsproject.cpp index 7240fab3a5..38257ad754 100644 --- a/src/plugins/autotoolsprojectmanager/autotoolsproject.cpp +++ b/src/plugins/autotoolsprojectmanager/autotoolsproject.cpp @@ -119,7 +119,7 @@ Project::RestoreResult AutotoolsProject::fromMap(const QVariantMap &map, QString void AutotoolsProject::loadProjectTree() { - if (m_makefileParserThread != 0) { + if (m_makefileParserThread) { // The thread is still busy parsing a previus configuration. // Wait until the thread has been finished and delete it. // TODO: Discuss whether blocking is acceptable. @@ -162,7 +162,7 @@ void AutotoolsProject::makefileParsingFinished() // The parsing has been cancelled by the user. Don't show any // project data at all. m_makefileParserThread->deleteLater(); - m_makefileParserThread = 0; + m_makefileParserThread = nullptr; return; } @@ -179,7 +179,7 @@ void AutotoolsProject::makefileParsingFinished() // Apply sources to m_files, which are returned at AutotoolsProject::files() const QFileInfo fileInfo = projectFilePath().toFileInfo(); const QDir dir = fileInfo.absoluteDir(); - QStringList files = m_makefileParserThread->sources(); + const QStringList files = m_makefileParserThread->sources(); foreach (const QString& file, files) m_files.append(dir.absoluteFilePath(file)); @@ -187,35 +187,36 @@ void AutotoolsProject::makefileParsingFinished() // has been changed, the project tree must be reparsed. const QStringList makefiles = m_makefileParserThread->makefiles(); foreach (const QString &makefile, makefiles) { - files.append(makefile); + const QString absMakefile = dir.absoluteFilePath(makefile); - const QString watchedFile = dir.absoluteFilePath(makefile); - m_fileWatcher->addFile(watchedFile, Utils::FileSystemWatcher::WatchAllChanges); - m_watchedFiles.append(watchedFile); + m_files.append(absMakefile); + + m_fileWatcher->addFile(absMakefile, Utils::FileSystemWatcher::WatchAllChanges); + m_watchedFiles.append(absMakefile); } // Add configure.ac file to project and watch for changes. const QLatin1String configureAc(QLatin1String("configure.ac")); const QFile configureAcFile(fileInfo.absolutePath() + QLatin1Char('/') + configureAc); if (configureAcFile.exists()) { - files.append(configureAc); - const QString configureAcFilePath = dir.absoluteFilePath(configureAc); - m_fileWatcher->addFile(configureAcFilePath, Utils::FileSystemWatcher::WatchAllChanges); - m_watchedFiles.append(configureAcFilePath); + const QString absConfigureAc = dir.absoluteFilePath(configureAc); + m_files.append(absConfigureAc); + + m_fileWatcher->addFile(absConfigureAc, Utils::FileSystemWatcher::WatchAllChanges); + m_watchedFiles.append(absConfigureAc); } auto newRoot = new AutotoolsProjectNode(projectDirectory()); - for (const QString &f : files) { - const Utils::FileName path = Utils::FileName::fromString(dir.absoluteFilePath(f)); - FileType ft = (f == "Makefile.am" || f == "configure.ac") ? FileType::Project : FileType::Resource; - newRoot->addNestedNode(new FileNode(path, ft, false)); + for (const QString &f : m_files) { + const Utils::FileName path = Utils::FileName::fromString(f); + newRoot->addNestedNode(new FileNode(path, FileNode::fileTypeForFileName(path), false)); } setRootProjectNode(newRoot); updateCppCodeModel(); m_makefileParserThread->deleteLater(); - m_makefileParserThread = 0; + m_makefileParserThread = nullptr; emit parsingFinished(); } diff --git a/src/plugins/cmakeprojectmanager/builddirmanager.cpp b/src/plugins/cmakeprojectmanager/builddirmanager.cpp index dbfc4825eb..ca2fd4bd6a 100644 --- a/src/plugins/cmakeprojectmanager/builddirmanager.cpp +++ b/src/plugins/cmakeprojectmanager/builddirmanager.cpp @@ -334,6 +334,8 @@ QList<CMakeBuildTarget> BuildDirManager::buildTargets() const m_buildTargets.append(utilityTarget(CMakeBuildStep::allTarget(), this)); m_buildTargets.append(utilityTarget(CMakeBuildStep::cleanTarget(), this)); m_buildTargets.append(utilityTarget(CMakeBuildStep::installTarget(), this)); + m_buildTargets.append(utilityTarget(CMakeBuildStep::testTarget(), this)); + m_buildTargets.append(m_reader->buildTargets()); } return m_buildTargets; diff --git a/src/plugins/cmakeprojectmanager/cmakebuildstep.cpp b/src/plugins/cmakeprojectmanager/cmakebuildstep.cpp index 1ecb3e4bc8..d87a538f98 100644 --- a/src/plugins/cmakeprojectmanager/cmakebuildstep.cpp +++ b/src/plugins/cmakeprojectmanager/cmakebuildstep.cpp @@ -404,9 +404,14 @@ QString CMakeBuildStep::installTarget() return QString("install"); } +QString CMakeBuildStep::testTarget() +{ + return QString("test"); +} + QStringList CMakeBuildStep::specialTargets() { - return { allTarget(), cleanTarget(), installTarget() }; + return { allTarget(), cleanTarget(), installTarget(), testTarget() }; } // diff --git a/src/plugins/cmakeprojectmanager/cmakebuildstep.h b/src/plugins/cmakeprojectmanager/cmakebuildstep.h index e740baeaa7..70d89c8783 100644 --- a/src/plugins/cmakeprojectmanager/cmakebuildstep.h +++ b/src/plugins/cmakeprojectmanager/cmakebuildstep.h @@ -80,6 +80,7 @@ public: static QString cleanTarget(); static QString allTarget(); static QString installTarget(); + static QString testTarget(); static QStringList specialTargets(); signals: diff --git a/src/plugins/cmakeprojectmanager/cmakeproject.cpp b/src/plugins/cmakeprojectmanager/cmakeproject.cpp index ce4c54a9fe..101649702c 100644 --- a/src/plugins/cmakeprojectmanager/cmakeproject.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeproject.cpp @@ -498,8 +498,10 @@ void CMakeProject::updateApplicationAndDeploymentTargets() if (ct.targetType == ExecutableType || ct.targetType == DynamicLibraryType) deploymentData.addFile(ct.executable.toString(), deploymentPrefix + buildDir.relativeFilePath(ct.executable.toFileInfo().dir().path()), DeployableFile::TypeExecutable); if (ct.targetType == ExecutableType) { + FileName srcWithTrailingSlash = FileName::fromString(ct.sourceDirectory.toString()); + srcWithTrailingSlash.appendString('/'); // TODO: Put a path to corresponding .cbp file into projectFilePath? - appTargetList.list << BuildTargetInfo(ct.title, ct.executable, ct.executable); + appTargetList.list << BuildTargetInfo(ct.title, ct.executable, srcWithTrailingSlash); } } diff --git a/src/plugins/cmakeprojectmanager/cmakerunconfiguration.cpp b/src/plugins/cmakeprojectmanager/cmakerunconfiguration.cpp index 1205953c8b..bfb4fcbc71 100644 --- a/src/plugins/cmakeprojectmanager/cmakerunconfiguration.cpp +++ b/src/plugins/cmakeprojectmanager/cmakerunconfiguration.cpp @@ -247,7 +247,7 @@ RunConfiguration *CMakeRunConfigurationFactory::doCreate(Target *parent, Core::I CMakeProject *project = static_cast<CMakeProject *>(parent->project()); const QString title(buildTargetFromId(id)); const CMakeBuildTarget &ct = project->buildTargetForTitle(title); - return new CMakeRunConfiguration(parent, id, ct.executable.toString(), ct.workingDirectory, ct.title); + return new CMakeRunConfiguration(parent, id, title, ct.workingDirectory, ct.title); } bool CMakeRunConfigurationFactory::canClone(Target *parent, RunConfiguration *source) const @@ -274,7 +274,8 @@ bool CMakeRunConfigurationFactory::canRestore(Target *parent, const QVariantMap RunConfiguration *CMakeRunConfigurationFactory::doRestore(Target *parent, const QVariantMap &map) { - return new CMakeRunConfiguration(parent, idFromMap(map), QString(), Utils::FileName(), QString()); + const Core::Id id = idFromMap(map); + return new CMakeRunConfiguration(parent, id, buildTargetFromId(id), Utils::FileName(), QString()); } QString CMakeRunConfigurationFactory::buildTargetFromId(Core::Id id) diff --git a/src/plugins/cmakeprojectmanager/servermodereader.cpp b/src/plugins/cmakeprojectmanager/servermodereader.cpp index 8bcc834688..84070ee98c 100644 --- a/src/plugins/cmakeprojectmanager/servermodereader.cpp +++ b/src/plugins/cmakeprojectmanager/servermodereader.cpp @@ -316,7 +316,7 @@ void ServerModeReader::updateCodeModel(CppTools::RawProjectParts &rpps) CppTools::RawProjectPart rpp; rpp.setProjectFileLocation(fg->target->sourceDirectory.toString() + "/CMakeLists.txt"); - rpp.setBuildSystemTarget(fg->target->name); + rpp.setBuildSystemTarget(fg->target->name + '|' + rpp.projectFile); rpp.setDisplayName(fg->target->name + QString::number(counter)); rpp.setDefines(defineArg.toUtf8()); rpp.setIncludePaths(includes); diff --git a/src/plugins/cmakeprojectmanager/tealeafreader.cpp b/src/plugins/cmakeprojectmanager/tealeafreader.cpp index 0bfcac1d68..8c37220f26 100644 --- a/src/plugins/cmakeprojectmanager/tealeafreader.cpp +++ b/src/plugins/cmakeprojectmanager/tealeafreader.cpp @@ -367,7 +367,7 @@ void TeaLeafReader::updateCodeModel(CppTools::RawProjectParts &rpps) includePaths += m_parameters.buildDirectory.toString(); CppTools::RawProjectPart rpp; rpp.setProjectFileLocation(QString()); // No project file information available! - rpp.setBuildSystemTarget(cbt.title); + rpp.setBuildSystemTarget(cbt.title + '|'); rpp.setIncludePaths(includePaths); CppTools::RawProjectPartFlags cProjectFlags; diff --git a/src/plugins/coreplugin/vcsmanager.cpp b/src/plugins/coreplugin/vcsmanager.cpp index cec5642968..28ebd38270 100644 --- a/src/plugins/coreplugin/vcsmanager.cpp +++ b/src/plugins/coreplugin/vcsmanager.cpp @@ -94,21 +94,6 @@ public: return nullptr; } - VcsInfo *findUpInCache(const QString &directory) - { - VcsInfo *result = nullptr; - const QChar slash = QLatin1Char('/'); - // Split the path, trying to find the matching repository. We start from the reverse - // in order to detected nested repositories correctly (say, a git checkout under SVN). - for (int pos = directory.size() - 1; pos >= 0; pos = directory.lastIndexOf(slash, pos) - 1) { - const QString directoryPart = directory.left(pos); - result = findInCache(directoryPart); - if (result) - break; - } - return result; - } - void clearCache() { m_cachedMatches.clear(); diff --git a/src/plugins/cppeditor/cppinsertvirtualmethods.cpp b/src/plugins/cppeditor/cppinsertvirtualmethods.cpp index 2d898353b2..655803cb03 100644 --- a/src/plugins/cppeditor/cppinsertvirtualmethods.cpp +++ b/src/plugins/cppeditor/cppinsertvirtualmethods.cpp @@ -588,7 +588,8 @@ public: for (Scope::iterator it = clazz->memberBegin(); it != clazz->memberEnd(); ++it) { if (const Function *func = (*it)->type()->asFunctionType()) { // Filter virtual destructors - if (func->name()->asDestructorNameId()) + const Name *name = func->name(); + if (!name || name->asDestructorNameId()) continue; const Function *firstVirtual = 0; diff --git a/src/plugins/cpptools/compileroptionsbuilder.cpp b/src/plugins/cpptools/compileroptionsbuilder.cpp index e21fedef4c..0d89c12f33 100644 --- a/src/plugins/cpptools/compileroptionsbuilder.cpp +++ b/src/plugins/cpptools/compileroptionsbuilder.cpp @@ -393,7 +393,7 @@ void CompilerOptionsBuilder::addDefineFloat128ForMingw() // CLANG-UPGRADE-CHECK: Workaround still needed? // https://llvm.org/bugs/show_bug.cgi?id=30685 if (m_projectPart.toolchainType == ProjectExplorer::Constants::MINGW_TOOLCHAIN_TYPEID) - addDefine("#define __float128 void"); + addDefine("#define __float128 short"); } QString CompilerOptionsBuilder::includeDirOption() const diff --git a/src/plugins/projectexplorer/projectmanager.h b/src/plugins/projectexplorer/projectmanager.h index 1e90f958c1..e504b1968e 100644 --- a/src/plugins/projectexplorer/projectmanager.h +++ b/src/plugins/projectexplorer/projectmanager.h @@ -27,6 +27,10 @@ #include "projectexplorer_export.h" +#include <QString> + +#include <functional> + namespace Utils { class FileName; class MimeType; diff --git a/src/plugins/qbsprojectmanager/qbsnodes.cpp b/src/plugins/qbsprojectmanager/qbsnodes.cpp index 262145ec6d..e3dd87e23e 100644 --- a/src/plugins/qbsprojectmanager/qbsnodes.cpp +++ b/src/plugins/qbsprojectmanager/qbsnodes.cpp @@ -454,7 +454,7 @@ QList<ProjectExplorer::RunConfiguration *> QbsProductNode::runConfigurations() c QbsRunConfiguration *qbsRc = qobject_cast<QbsRunConfiguration *>(rc); if (!qbsRc) continue; - if (qbsRc->buildSystemTarget() == QbsProject::uniqueProductName(qbsProductData())) + if (qbsRc->uniqueProductName() == QbsProject::uniqueProductName(qbsProductData())) result << qbsRc; } diff --git a/src/plugins/qbsprojectmanager/qbsproject.cpp b/src/plugins/qbsprojectmanager/qbsproject.cpp index e459d26a89..251c4f08b5 100644 --- a/src/plugins/qbsprojectmanager/qbsproject.cpp +++ b/src/plugins/qbsprojectmanager/qbsproject.cpp @@ -161,6 +161,8 @@ QbsProject::~QbsProject() m_qbsUpdateFutureInterface = 0; } qDeleteAll(m_extraCompilers); + std::for_each(m_qbsDocuments.cbegin(), m_qbsDocuments.cend(), + [](Core::IDocument *doc) { doc->deleteLater(); }); } QbsRootProjectNode *QbsProject::rootProjectNode() const @@ -974,7 +976,7 @@ void QbsProject::updateCppCodeModel() rpp.setDisplayName(grp.name()); rpp.setProjectFileLocation(grp.location().filePath(), grp.location().line(), grp.location().column()); - rpp.setBuildSystemTarget(uniqueProductName(prd)); + rpp.setBuildSystemTarget(prd.name() + '|' + rpp.projectFile); QHash<QString, qbs::ArtifactData> filePathToSourceArtifact; bool hasCFiles = false; diff --git a/src/plugins/qbsprojectmanager/qbsrunconfiguration.cpp b/src/plugins/qbsprojectmanager/qbsrunconfiguration.cpp index 7f7e687d56..e8b90d4377 100644 --- a/src/plugins/qbsprojectmanager/qbsrunconfiguration.cpp +++ b/src/plugins/qbsprojectmanager/qbsrunconfiguration.cpp @@ -301,6 +301,11 @@ void QbsRunConfiguration::addToBaseEnvironment(Utils::Environment &env) const QString QbsRunConfiguration::buildSystemTarget() const { + return productDisplayNameFromId(id()); +} + +QString QbsRunConfiguration::uniqueProductName() const +{ return m_uniqueProductName; } diff --git a/src/plugins/qbsprojectmanager/qbsrunconfiguration.h b/src/plugins/qbsprojectmanager/qbsrunconfiguration.h index 45b4c3b830..bff341af46 100644 --- a/src/plugins/qbsprojectmanager/qbsrunconfiguration.h +++ b/src/plugins/qbsprojectmanager/qbsrunconfiguration.h @@ -76,6 +76,7 @@ public: void addToBaseEnvironment(Utils::Environment &env) const; QString buildSystemTarget() const final; + QString uniqueProductName() const; bool isConsoleApplication() const; signals: diff --git a/src/plugins/qmakeprojectmanager/qmakeproject.cpp b/src/plugins/qmakeprojectmanager/qmakeproject.cpp index c241189d9e..806e500e57 100644 --- a/src/plugins/qmakeprojectmanager/qmakeproject.cpp +++ b/src/plugins/qmakeprojectmanager/qmakeproject.cpp @@ -287,7 +287,7 @@ void QmakeProject::updateCppCodeModel() CppTools::RawProjectPart rpp; rpp.setDisplayName(pro->displayName()); rpp.setProjectFileLocation(pro->filePath().toString()); - rpp.setBuildSystemTarget(pro->targetInformation().target); + rpp.setBuildSystemTarget(pro->targetInformation().target + '|' + rpp.projectFile); // TODO: Handle QMAKE_CFLAGS rpp.setFlagsForCxx({cxxToolChain, pro->variableValue(Variable::CppFlags)}); rpp.setDefines(pro->cxxDefines()); diff --git a/src/plugins/qmakeprojectmanager/qmakeprojectmanager.cpp b/src/plugins/qmakeprojectmanager/qmakeprojectmanager.cpp index 766e951345..666ec0ce51 100644 --- a/src/plugins/qmakeprojectmanager/qmakeprojectmanager.cpp +++ b/src/plugins/qmakeprojectmanager/qmakeprojectmanager.cpp @@ -95,13 +95,22 @@ void QmakeManager::addLibrary() void QmakeManager::addLibraryContextMenu() { + QString projectPath; + Node *node = contextNode(); - if (dynamic_cast<QmakeProFileNode *>(node)) - addLibraryImpl(node->filePath().toString(), nullptr); + if (ContainerNode *cn = node->asContainerNode()) + projectPath = cn->project()->projectFilePath().toString(); + else if (dynamic_cast<QmakeProFileNode *>(node)) + projectPath = node->filePath().toString(); + + addLibraryImpl(projectPath, nullptr); } void QmakeManager::addLibraryImpl(const QString &fileName, BaseTextEditor *editor) { + if (fileName.isEmpty()) + return; + Internal::AddLibraryWizard wizard(fileName, Core::ICore::dialogParent()); if (wizard.exec() != QDialog::Accepted) return; diff --git a/src/plugins/qmakeprojectmanager/qmakestep.cpp b/src/plugins/qmakeprojectmanager/qmakestep.cpp index 99dab8044d..54c8d0989d 100644 --- a/src/plugins/qmakeprojectmanager/qmakestep.cpp +++ b/src/plugins/qmakeprojectmanager/qmakestep.cpp @@ -225,19 +225,18 @@ bool QMakeStep::init(QList<const BuildStep *> &earlierSteps) m_makeArguments.clear(); } - QString makefile = workingDirectory; + QString makefile = workingDirectory + '/'; if (qmakeBc->subNodeBuild()) { QmakeProFile *pro = qmakeBc->subNodeBuild()->proFile(); if (pro && !pro->makefile().isEmpty()) makefile.append(pro->makefile()); else - makefile.append(QLatin1String("/Makefile")); + makefile.append("Makefile"); } else if (!qmakeBc->makefile().isEmpty()) { - makefile.append(QLatin1Char('/')); makefile.append(qmakeBc->makefile()); } else { - makefile.append(QLatin1String("/Makefile")); + makefile.append("Makefile"); } // Check whether we need to run qmake diff --git a/src/plugins/updateinfo/updateinfoplugin.cpp b/src/plugins/updateinfo/updateinfoplugin.cpp index ec59aa52ea..f54d15fd5e 100644 --- a/src/plugins/updateinfo/updateinfoplugin.cpp +++ b/src/plugins/updateinfo/updateinfoplugin.cpp @@ -213,6 +213,7 @@ bool UpdateInfoPlugin::initialize(const QStringList & /* arguments */, QString * addAutoReleasedObject(new SettingsPage(this)); QAction *checkForUpdatesAction = new QAction(tr("Check for Updates"), this); + checkForUpdatesAction->setMenuRole(QAction::ApplicationSpecificRole); Core::Command *checkForUpdatesCommand = Core::ActionManager::registerAction(checkForUpdatesAction, "Updates.CheckForUpdates"); connect(checkForUpdatesAction, &QAction::triggered, this, &UpdateInfoPlugin::startCheckForUpdates); ActionContainer *const helpContainer = ActionManager::actionContainer(Core::Constants::M_HELP); diff --git a/src/plugins/vcsbase/vcsbasesubmiteditor.cpp b/src/plugins/vcsbase/vcsbasesubmiteditor.cpp index 97e47eac2d..a06b43ca06 100644 --- a/src/plugins/vcsbase/vcsbasesubmiteditor.cpp +++ b/src/plugins/vcsbase/vcsbasesubmiteditor.cpp @@ -50,6 +50,7 @@ #include <texteditor/texteditorsettings.h> #include <projectexplorer/project.h> +#include <projectexplorer/session.h> #include <QDir> #include <QFileInfo> @@ -722,22 +723,10 @@ QIcon VcsBaseSubmitEditor::submitIcon() void VcsBaseSubmitEditor::filterUntrackedFilesOfProject(const QString &repositoryDirectory, QStringList *untrackedFiles) { - if (untrackedFiles->empty()) - return; - - ProjectExplorer::Project *vcsProject = VcsProjectCache::projectFor(repositoryDirectory); - if (!vcsProject) - return; - - const QSet<QString> projectFiles - = QSet<QString>::fromList(vcsProject->files(ProjectExplorer::Project::SourceFiles)); - - if (projectFiles.empty()) - return; const QDir repoDir(repositoryDirectory); for (QStringList::iterator it = untrackedFiles->begin(); it != untrackedFiles->end(); ) { const QString path = repoDir.absoluteFilePath(*it); - if (projectFiles.contains(path)) + if (ProjectExplorer::SessionManager::projectForFile(FileName::fromString(path))) ++it; else it = untrackedFiles->erase(it); diff --git a/src/plugins/welcome/welcomeplugin.cpp b/src/plugins/welcome/welcomeplugin.cpp index 8a34fdd466..c7d6058012 100644 --- a/src/plugins/welcome/welcomeplugin.cpp +++ b/src/plugins/welcome/welcomeplugin.cpp @@ -48,6 +48,7 @@ #include <QHeaderView> #include <QLabel> #include <QMouseEvent> +#include <QOpenGLWidget> #include <QPainter> #include <QStackedWidget> #include <QTimer> @@ -310,6 +311,12 @@ WelcomeMode::WelcomeMode() layout->addWidget(new StyledBar(m_modeWidget)); layout->addItem(hbox); + if (Utils::HostOsInfo::isMacHost()) { // workaround QTBUG-61384 + auto openglWidget = new QOpenGLWidget; + openglWidget->hide(); + layout->addWidget(openglWidget); + } + setWidget(m_modeWidget); } |