diff --git a/doc/images/qtcreator-todo-options.png b/doc/images/qtcreator-todo-options.png new file mode 100644 index 00000000000..acf1a1ee906 Binary files /dev/null and b/doc/images/qtcreator-todo-options.png differ diff --git a/doc/images/qtcreator-todo-pane.png b/doc/images/qtcreator-todo-pane.png index 73908e1538f..eed8e3deba4 100644 Binary files a/doc/images/qtcreator-todo-pane.png and b/doc/images/qtcreator-todo-pane.png differ diff --git a/doc/src/howto/creator-ui.qdoc b/doc/src/howto/creator-ui.qdoc index f00a025aadb..71e197e8d8b 100644 --- a/doc/src/howto/creator-ui.qdoc +++ b/doc/src/howto/creator-ui.qdoc @@ -504,20 +504,32 @@ \section2 To-Do Entries The \uicontrol {To-Do Entries} pane lists the BUG, FIXME, NOTE, TODO, and - WARNING keywords from the current file or from all project files. The - keywords are organized into information, warning, and error categories. + WARNING keywords from the current file, from all project files, or from a + subproject. Click the icons on the toolbar to show only the selected + keywords. \image qtcreator-todo-pane.png To add keywords, select \uicontrol Tools > \uicontrol Options > - \uicontrol {To-Do} > \uicontrol Add. - Set an icon and a line background color for the keyword. To change the icons - and colors set for an existing keyword, select \uicontrol Edit. + \uicontrol {To-Do} > \uicontrol Add. Set an icon and a line background color + for the keyword. - To determine whether the keywords in the whole project or in the current - file are displayed by default, select \uicontrol {Scanning scope}. + \image qtcreator-todo-options.png - To exclude files from scanning, select \uicontrol {To-Do} in the + To change the icon and line background color of the selected keyword, select + \uicontrol Edit. + + To remove the selected keyword, select \uicontrol Remove. + + To reset the list to predefined keywords, select \uicontrol Reset. All your + changes will be permanently lost. + + To determine whether the keywords in the whole project, in the current file, + or in a subproject are displayed by default, select the appropriate option + in the \uicontrol {Scanning scope} group. + + To exclude files from scanning, select \uicontrol {Project Settings} > + \uicontrol {To-Do} in the \uicontrol Projects mode. Select \uicontrol Add and enter a regular expression that matches the path to files to exclude. Use a forward slash (/) as a separator in the path also on Windows. diff --git a/share/qtcreator/debugger/dumper.py b/share/qtcreator/debugger/dumper.py index 3ca3620c420..3f972603e5b 100644 --- a/share/qtcreator/debugger/dumper.py +++ b/share/qtcreator/debugger/dumper.py @@ -1320,12 +1320,12 @@ class DumperBase: derefValue.name = '*' self.putItem(derefValue) self.currentChildType = savedCurrentChildType - self.putAddress(value.address()) def putFormattedPointerX(self, value): self.putOriginalAddress(value.address()) #warn("PUT FORMATTED: %s" % value) pointer = value.pointer() + self.putAddress(pointer) #warn('POINTER: 0x%x' % pointer) if pointer == 0: #warn('NULL POINTER') diff --git a/share/qtcreator/translations/qtcreator_da.ts b/share/qtcreator/translations/qtcreator_da.ts old mode 100755 new mode 100644 diff --git a/src/app/main.cpp b/src/app/main.cpp index feecacb858f..315108195a5 100644 --- a/src/app/main.cpp +++ b/src/app/main.cpp @@ -280,6 +280,9 @@ void loadFonts() int main(int argc, char **argv) { + if (Utils::HostOsInfo::isLinuxHost()) + QApplication::setAttribute(Qt::AA_DontUseNativeMenuBar); + Utils::TemporaryDirectory::setMasterTemporaryDirectory(QDir::tempPath() + "/QtCreator-XXXXXX"); const char *highDpiEnvironmentVariable = setHighDpiEnvironmentVariable(); diff --git a/src/libs/cplusplus/pp-engine.cpp b/src/libs/cplusplus/pp-engine.cpp index 5f2e543c52e..3ef5e2c38e0 100644 --- a/src/libs/cplusplus/pp-engine.cpp +++ b/src/libs/cplusplus/pp-engine.cpp @@ -99,7 +99,7 @@ static bool isQtReservedWord(const char *name, int size) size -= 2; switch (size) { case 1: - return name[2] == 'D' || name[2] == 'Q'; + return name[0] == 'D' || name[0] == 'Q'; case 4: return same(name, "SLOT", size) || same(name, "EMIT", size); case 5: diff --git a/src/libs/utils/temporarydirectory.cpp b/src/libs/utils/temporarydirectory.cpp index c0d0c15cb1b..da539919e42 100644 --- a/src/libs/utils/temporarydirectory.cpp +++ b/src/libs/utils/temporarydirectory.cpp @@ -25,13 +25,19 @@ #include "temporarydirectory.h" -#include "qtcassert.h" +#include -#include +#include "qtcassert.h" namespace Utils { -static std::unique_ptr m_masterTemporaryDir; +static QTemporaryDir* m_masterTemporaryDir = nullptr; + +static void cleanupMasterTemporaryDir() +{ + delete m_masterTemporaryDir; + m_masterTemporaryDir = nullptr; +} TemporaryDirectory::TemporaryDirectory(const QString &pattern) : QTemporaryDir(m_masterTemporaryDir->path() + '/' + pattern) @@ -41,12 +47,16 @@ TemporaryDirectory::TemporaryDirectory(const QString &pattern) : QTemporaryDir *TemporaryDirectory::masterTemporaryDirectory() { - return m_masterTemporaryDir.get(); + return m_masterTemporaryDir; } void TemporaryDirectory::setMasterTemporaryDirectory(const QString &pattern) { - m_masterTemporaryDir = std::make_unique(pattern); + if (m_masterTemporaryDir) + cleanupMasterTemporaryDir(); + else + qAddPostRoutine(cleanupMasterTemporaryDir); + m_masterTemporaryDir = new QTemporaryDir(pattern); } QString TemporaryDirectory::masterDirectoryPath() diff --git a/src/libs/utils/textfieldcheckbox.h b/src/libs/utils/textfieldcheckbox.h index 9bcc17c9ad6..ad585255efc 100644 --- a/src/libs/utils/textfieldcheckbox.h +++ b/src/libs/utils/textfieldcheckbox.h @@ -33,7 +33,7 @@ namespace Utils { // Documentation inside. class QTCREATOR_UTILS_EXPORT TextFieldCheckBox : public QCheckBox { - Q_PROPERTY(QString text READ text WRITE setText) + Q_PROPERTY(QString compareText READ text WRITE setText) Q_PROPERTY(QString trueText READ trueText WRITE setTrueText) Q_PROPERTY(QString falseText READ falseText WRITE setFalseText) Q_OBJECT diff --git a/src/libs/utils/textfieldcombobox.h b/src/libs/utils/textfieldcombobox.h index 136b85de3c7..937a290cad2 100644 --- a/src/libs/utils/textfieldcombobox.h +++ b/src/libs/utils/textfieldcombobox.h @@ -33,7 +33,7 @@ namespace Utils { // Documentation inside. class QTCREATOR_UTILS_EXPORT TextFieldComboBox : public QComboBox { - Q_PROPERTY(QString text READ text WRITE setText) + Q_PROPERTY(QString indexText READ text WRITE setText) Q_OBJECT public: explicit TextFieldComboBox(QWidget *parent = 0); diff --git a/src/plugins/autotest/testcodeparser.cpp b/src/plugins/autotest/testcodeparser.cpp index f12e418b220..001ea5d48b0 100644 --- a/src/plugins/autotest/testcodeparser.cpp +++ b/src/plugins/autotest/testcodeparser.cpp @@ -55,6 +55,8 @@ static Q_LOGGING_CATEGORY(LOG, "qtc.autotest.testcodeparser") namespace Autotest { namespace Internal { +using namespace ProjectExplorer; + TestCodeParser::TestCodeParser(TestTreeModel *parent) : QObject(parent), m_model(parent) @@ -100,7 +102,7 @@ void TestCodeParser::setState(State state) } m_parserState = state; - if (m_parserState == Idle && ProjectExplorer::SessionManager::startupProject()) { + if (m_parserState == Idle && SessionManager::startupProject()) { if (m_fullUpdatePostponed || m_dirty) { emitUpdateTestTree(); } else if (m_partialUpdatePostponed) { @@ -160,7 +162,7 @@ void TestCodeParser::updateTestTree(ITestParser *parser) return; } - if (!ProjectExplorer::SessionManager::startupProject()) + if (!SessionManager::startupProject()) return; m_fullUpdatePostponed = false; @@ -201,10 +203,10 @@ void TestCodeParser::onDocumentUpdated(const QString &fileName) if (m_codeModelParsing || m_fullUpdatePostponed) return; - ProjectExplorer::Project *project = ProjectExplorer::SessionManager::startupProject(); + Project *project = SessionManager::startupProject(); if (!project) return; - if (!project->files(ProjectExplorer::Project::SourceFiles).contains(fileName)) + if (!SessionManager::projectContainsFile(project, Utils::FileName::fromString(fileName))) return; scanForTests(QStringList(fileName)); @@ -222,7 +224,7 @@ void TestCodeParser::onQmlDocumentUpdated(const QmlJS::Document::Ptr &document) onDocumentUpdated(fileName); } -void TestCodeParser::onStartupProjectChanged(ProjectExplorer::Project *project) +void TestCodeParser::onStartupProjectChanged(Project *project) { if (m_parserState == FullParse || m_parserState == PartialParse) { qCDebug(LOG) << "Canceling scanForTest (startup project changed)"; @@ -233,9 +235,9 @@ void TestCodeParser::onStartupProjectChanged(ProjectExplorer::Project *project) emitUpdateTestTree(); } -void TestCodeParser::onProjectPartsUpdated(ProjectExplorer::Project *project) +void TestCodeParser::onProjectPartsUpdated(Project *project) { - if (project != ProjectExplorer::SessionManager::startupProject()) + if (project != SessionManager::startupProject()) return; if (m_codeModelParsing) m_fullUpdatePostponed = true; @@ -334,12 +336,12 @@ void TestCodeParser::scanForTests(const QStringList &fileList, ITestParser *pars m_reparseTimerTimedOut = false; m_postponedFiles.clear(); bool isFullParse = fileList.isEmpty(); - ProjectExplorer::Project *project = ProjectExplorer::SessionManager::startupProject(); + Project *project = SessionManager::startupProject(); if (!project) return; QStringList list; if (isFullParse) { - list = project->files(ProjectExplorer::Project::SourceFiles); + list = project->files(Project::SourceFiles); if (list.isEmpty()) { // at least project file should be there, but might happen if parsing current project // takes too long, especially when opening sessions holding multiple projects diff --git a/src/plugins/cmakeprojectmanager/servermodereader.cpp b/src/plugins/cmakeprojectmanager/servermodereader.cpp index b2cf1517c6b..a3a06b2a8b3 100644 --- a/src/plugins/cmakeprojectmanager/servermodereader.cpp +++ b/src/plugins/cmakeprojectmanager/servermodereader.cpp @@ -401,7 +401,8 @@ void ServerModeReader::handleProgress(int min, int cur, int max, const QString & void ServerModeReader::handleSignal(const QString &signal, const QVariantMap &data) { Q_UNUSED(data); - if (signal == "dirty") + // CMake on Windows sends false dirty signals on each edit (QTCREATORBUG-17944) + if (!HostOsInfo::isWindowsHost() && signal == "dirty") emit dirty(); } @@ -706,14 +707,15 @@ void ServerModeReader::addFileGroups(ProjectNode *targetRoot, } // Split up files in groups (based on location): + const bool inSourceBuild = (m_parameters.buildDirectory == m_parameters.sourceDirectory); QList sourceFileNodes; QList buildFileNodes; QList otherFileNodes; foreach (FileNode *fn, toList) { - if (fn->filePath().isChildOf(m_parameters.sourceDirectory)) - sourceFileNodes.append(fn); - else if (fn->filePath().isChildOf(m_parameters.buildDirectory)) + if (fn->filePath().isChildOf(m_parameters.buildDirectory) && !inSourceBuild) buildFileNodes.append(fn); + else if (fn->filePath().isChildOf(m_parameters.sourceDirectory)) + sourceFileNodes.append(fn); else otherFileNodes.append(fn); } diff --git a/src/plugins/cpaster/pastebindotcaprotocol.cpp b/src/plugins/cpaster/pastebindotcaprotocol.cpp index aeb83d20d4e..b6fac76b6c1 100644 --- a/src/plugins/cpaster/pastebindotcaprotocol.cpp +++ b/src/plugins/cpaster/pastebindotcaprotocol.cpp @@ -34,8 +34,8 @@ #include #include -static const char urlC[] = "http://pastebin.ca/"; -static const char internalUrlC[] = "http://pbin.ca/"; +static const char urlC[] = "https://pastebin.ca/"; +static const char internalUrlC[] = "https://pbin.ca/"; static const char protocolNameC[] = "Pastebin.Ca"; static inline QByteArray expiryValue(int expiryDays) diff --git a/src/plugins/debugger/debuggeritemmanager.cpp b/src/plugins/debugger/debuggeritemmanager.cpp index 0b473fd93eb..6bdf2ca9801 100644 --- a/src/plugins/debugger/debuggeritemmanager.cpp +++ b/src/plugins/debugger/debuggeritemmanager.cpp @@ -197,8 +197,9 @@ public: void updateDebugger(const DebuggerItem &item); void apply(); void cancel(); + DebuggerTreeItem *currentTreeItem(); - DebuggerTreeItem *m_currentTreeItem = nullptr; + QPersistentModelIndex m_currentIndex; }; template @@ -287,8 +288,13 @@ void DebuggerItemModel::cancel() void DebuggerItemModel::setCurrentIndex(const QModelIndex &index) { - TreeItem *treeItem = itemForIndex(index); - m_currentTreeItem = treeItem && treeItem->level() == 2 ? static_cast(treeItem) : 0; + m_currentIndex = index; +} + +DebuggerTreeItem *DebuggerItemModel::currentTreeItem() +{ + TreeItem *treeItem = itemForIndex(m_currentIndex); + return treeItem && treeItem->level() == 2 ? static_cast(treeItem) : nullptr; } DebuggerItemConfigWidget::DebuggerItemConfigWidget() @@ -514,10 +520,11 @@ public: void DebuggerConfigWidget::cloneDebugger() { - if (!d->m_model->m_currentTreeItem) + DebuggerTreeItem *treeItem = d->m_model->currentTreeItem(); + if (!treeItem) return; - DebuggerItem *item = &d->m_model->m_currentTreeItem->m_item; + DebuggerItem *item = &treeItem->m_item; DebuggerItem newItem; newItem.createId(); newItem.setCommand(item->command()); @@ -542,9 +549,10 @@ void DebuggerConfigWidget::addDebugger() void DebuggerConfigWidget::removeDebugger() { - QTC_ASSERT(d->m_model->m_currentTreeItem, return); - d->m_model->m_currentTreeItem->m_removed = !d->m_model->m_currentTreeItem->m_removed; - d->m_model->m_currentTreeItem->update(); + DebuggerTreeItem *treeItem = d->m_model->currentTreeItem(); + QTC_ASSERT(treeItem, return); + treeItem->m_removed = !treeItem->m_removed; + treeItem->update(); updateButtons(); } @@ -556,7 +564,7 @@ void DebuggerConfigWidget::currentDebuggerChanged(const QModelIndex &newCurrent) void DebuggerConfigWidget::updateButtons() { - DebuggerTreeItem *titem = d->m_model->m_currentTreeItem; + DebuggerTreeItem *titem = d->m_model->currentTreeItem(); DebuggerItem *item = titem ? &titem->m_item : nullptr; m_itemConfigWidget->load(item); diff --git a/src/plugins/git/gerrit/gerritmodel.cpp b/src/plugins/git/gerrit/gerritmodel.cpp index 16a303d50a0..36e24ae292c 100644 --- a/src/plugins/git/gerrit/gerritmodel.cpp +++ b/src/plugins/git/gerrit/gerritmodel.cpp @@ -230,6 +230,7 @@ public: ~QueryContext(); void start(); + void terminate(); signals: void resultRetrieved(const QByteArray &); @@ -242,7 +243,6 @@ private: void timeout(); void errorTermination(const QString &msg); - void terminate(); QProcess m_process; QTimer m_timer; @@ -498,10 +498,8 @@ QStandardItem *GerritModel::itemForNumber(int number) const void GerritModel::refresh(const QSharedPointer &server, const QString &query) { - if (m_query) { - qWarning("%s: Another query is still running", Q_FUNC_INFO); - return; - } + if (m_query) + m_query->terminate(); clearData(); m_server = server; @@ -655,7 +653,7 @@ static GerritChangePtr parseSshOutput(const QJsonObject &object) { "value": 0, "_account_id": 1000528, - "name": "André Hartmann", + "name": "Andre Hartmann", "email": "aha_1980@gmx.de" }, { @@ -684,7 +682,7 @@ static GerritChangePtr parseSshOutput(const QJsonObject &object) { "value": 0, "_account_id": 1000528, - "name": "André Hartmann", + "name": "Andre Hartmann", "email": "aha_1980@gmx.de" }, { diff --git a/src/plugins/ios/iostoolhandler.cpp b/src/plugins/ios/iostoolhandler.cpp index 4795d922a0c..895397ffbe9 100644 --- a/src/plugins/ios/iostoolhandler.cpp +++ b/src/plugins/ios/iostoolhandler.cpp @@ -248,6 +248,7 @@ class IosDeviceToolHandlerPrivate : public IosToolHandlerPrivate { public: explicit IosDeviceToolHandlerPrivate(const IosDeviceType &devType, IosToolHandler *q); + ~IosDeviceToolHandlerPrivate(); // IosToolHandlerPrivate overrides public: @@ -656,8 +657,11 @@ IosDeviceToolHandlerPrivate::IosDeviceToolHandlerPrivate(const IosDeviceType &de : IosToolHandlerPrivate(devType, q) { auto deleter = [](QProcess *p) { - p->kill(); - p->waitForFinished(10000); + if (p->state() != QProcess::NotRunning) { + p->kill(); + if (!p->waitForFinished(2000)) + p->terminate(); + } delete p; }; process = std::shared_ptr(new QProcess, deleter); @@ -696,6 +700,20 @@ IosDeviceToolHandlerPrivate::IosDeviceToolHandlerPrivate(const IosDeviceType &de QObject::connect(&killTimer, &QTimer::timeout, std::bind(&IosDeviceToolHandlerPrivate::killProcess, this)); } +IosDeviceToolHandlerPrivate::~IosDeviceToolHandlerPrivate() +{ + if (isRunning()) { + // Disconnect the signals to avoid notifications while destructing. + // QTCREATORBUG-18147 + process->disconnect(); + // Quit ios-tool gracefully before kill is executed. + process->write("k\n\r"); + process->closeWriteChannel(); + // Give some time to ios-tool to finish. + process->waitForFinished(2000); + } +} + void IosDeviceToolHandlerPrivate::requestTransferApp(const QString &bundlePath, const QString &deviceId, int timeout) { diff --git a/src/plugins/projectexplorer/jsonwizard/jsonfieldpage.cpp b/src/plugins/projectexplorer/jsonwizard/jsonfieldpage.cpp index f71bdd19e2e..bb859d7a51a 100644 --- a/src/plugins/projectexplorer/jsonwizard/jsonfieldpage.cpp +++ b/src/plugins/projectexplorer/jsonwizard/jsonfieldpage.cpp @@ -689,7 +689,7 @@ void CheckBoxField::setup(JsonFieldPage *page, const QString &name) auto w = static_cast(widget()); QObject::connect(w, &TextFieldCheckBox::clicked, page, [this, page]() { m_isModified = true; page->completeChanged();}); - page->registerFieldWithName(name, w, "text", SIGNAL(textChanged(QString))); + page->registerFieldWithName(name, w, "compareText", SIGNAL(textChanged(QString))); } bool CheckBoxField::validate(MacroExpander *expander, QString *message) @@ -822,7 +822,7 @@ QWidget *ComboBoxField::createWidget(const QString &displayName, JsonFieldPage * void ComboBoxField::setup(JsonFieldPage *page, const QString &name) { auto w = static_cast(widget()); - page->registerFieldWithName(name, w, "text", SIGNAL(text4Changed(QString))); + page->registerFieldWithName(name, w, "indexText", SIGNAL(text4Changed(QString))); QObject::connect(w, &TextFieldComboBox::text4Changed, page, [page](QString) { page->completeChanged(); }); } diff --git a/src/plugins/projectexplorer/projectexplorer.cpp b/src/plugins/projectexplorer/projectexplorer.cpp index c18c65a13cf..833ef2fdb8b 100644 --- a/src/plugins/projectexplorer/projectexplorer.cpp +++ b/src/plugins/projectexplorer/projectexplorer.cpp @@ -3312,6 +3312,7 @@ void ProjectExplorerPlugin::renameFile(Node *node, const QString &newFilePath) { const QString oldFilePath = node->filePath().toFileInfo().absoluteFilePath(); FolderNode *folderNode = node->parentFolderNode(); + QTC_ASSERT(folderNode, return); const QString projectFileName = folderNode->managingProject()->filePath().fileName(); if (oldFilePath == newFilePath) diff --git a/src/plugins/projectexplorer/runconfiguration.h b/src/plugins/projectexplorer/runconfiguration.h index dab5a3b9658..368e95978fd 100644 --- a/src/plugins/projectexplorer/runconfiguration.h +++ b/src/plugins/projectexplorer/runconfiguration.h @@ -175,7 +175,7 @@ class PROJECTEXPLORER_EXPORT Runnable public: Runnable() = default; - Runnable(const Runnable &other) : d(other.d->clone()) { } + Runnable(const Runnable &other) : d(other.d ? other.d->clone() : nullptr) { } Runnable(Runnable &&other) : d(std::move(other.d)) {} template Runnable(const T &data) : d(new Model(data)) {} @@ -215,7 +215,7 @@ class PROJECTEXPLORER_EXPORT Connection public: Connection() = default; - Connection(const Connection &other) : d(other.d->clone()) { } + Connection(const Connection &other) : d(other.d ? other.d->clone() : nullptr) { } Connection(Connection &&other) /* MSVC 2013 doesn't want = default */ : d(std::move(other.d)) {} template Connection(const T &data) : d(new Model(data)) {} diff --git a/src/plugins/projectexplorer/session.cpp b/src/plugins/projectexplorer/session.cpp index 5b8e6d382c0..432915f7770 100644 --- a/src/plugins/projectexplorer/session.cpp +++ b/src/plugins/projectexplorer/session.cpp @@ -74,7 +74,6 @@ namespace ProjectExplorer { class SessionManagerPrivate { public: - bool projectContainsFile(Project *p, const FileName &fileName) const; void restoreValues(const PersistentSettingsReader &reader); void restoreDependencies(const PersistentSettingsReader &reader); void restoreStartupProject(const PersistentSettingsReader &reader); @@ -658,19 +657,19 @@ Project *SessionManager::projectForFile(const Utils::FileName &fileName) { const QList &projectList = projects(); foreach (Project *p, projectList) { - if (d->projectContainsFile(p, fileName)) + if (projectContainsFile(p, fileName)) return p; } return nullptr; } -bool SessionManagerPrivate::projectContainsFile(Project *p, const Utils::FileName &fileName) const +bool SessionManager::projectContainsFile(Project *p, const Utils::FileName &fileName) { - if (!m_projectFileCache.contains(p)) - m_projectFileCache.insert(p, p->files(Project::AllFiles)); + if (!d->m_projectFileCache.contains(p)) + d->m_projectFileCache.insert(p, p->files(Project::AllFiles)); - return m_projectFileCache.value(p).contains(fileName.toString()); + return d->m_projectFileCache.value(p).contains(fileName.toString()); } void SessionManager::configureEditor(IEditor *editor, const QString &fileName) @@ -686,7 +685,7 @@ void SessionManager::configureEditor(IEditor *editor, const QString &fileName) void SessionManager::configureEditors(Project *project) { foreach (IDocument *document, DocumentModel::openedDocuments()) { - if (d->projectContainsFile(project, document->filePath())) { + if (projectContainsFile(project, document->filePath())) { foreach (IEditor *editor, DocumentModel::editorsForDocument(document)) { if (auto textEditor = qobject_cast(editor)) { project->editorConfiguration()->configureEditor(textEditor); diff --git a/src/plugins/projectexplorer/session.h b/src/plugins/projectexplorer/session.h index 8d6987363a4..a229ce58e14 100644 --- a/src/plugins/projectexplorer/session.h +++ b/src/plugins/projectexplorer/session.h @@ -115,6 +115,7 @@ public: static Project *projectForNode(Node *node); static Node *nodeForFile(const Utils::FileName &fileName); static Project *projectForFile(const Utils::FileName &fileName); + static bool projectContainsFile(Project *p, const Utils::FileName &fileName); static QStringList projectsForSessionName(const QString &session); diff --git a/src/plugins/qbsprojectmanager/qbsproject.cpp b/src/plugins/qbsprojectmanager/qbsproject.cpp index 33e28018cdd..c6366f9e323 100644 --- a/src/plugins/qbsprojectmanager/qbsproject.cpp +++ b/src/plugins/qbsprojectmanager/qbsproject.cpp @@ -738,7 +738,7 @@ void QbsProject::updateDocuments(const QSet &files) foreach (IDocument *doc, currentDocuments) { if (filesToRemove.contains(doc->filePath().toString())) { m_qbsDocuments.remove(doc); - delete doc; + doc->deleteLater(); } } QSet toAdd; diff --git a/src/plugins/qmakeprojectmanager/desktopqmakerunconfiguration.cpp b/src/plugins/qmakeprojectmanager/desktopqmakerunconfiguration.cpp index 2e0cb4ba395..a4a1302769e 100644 --- a/src/plugins/qmakeprojectmanager/desktopqmakerunconfiguration.cpp +++ b/src/plugins/qmakeprojectmanager/desktopqmakerunconfiguration.cpp @@ -262,6 +262,7 @@ DesktopQmakeRunConfigurationWidget::DesktopQmakeRunConfigurationWidget(DesktopQm this, &DesktopQmakeRunConfigurationWidget::runConfigurationEnabledChange); Core::VariableChooser::addSupportForChildWidgets(this, m_qmakeRunConfiguration->macroExpander()); + effectiveTargetInformationChanged(); } void DesktopQmakeRunConfigurationWidget::runConfigurationEnabledChange() diff --git a/src/plugins/qmakeprojectmanager/qmakenodes.cpp b/src/plugins/qmakeprojectmanager/qmakenodes.cpp index 98c0cae52e9..007e47b0180 100644 --- a/src/plugins/qmakeprojectmanager/qmakenodes.cpp +++ b/src/plugins/qmakeprojectmanager/qmakenodes.cpp @@ -84,9 +84,11 @@ bool QmakePriFileNode::supportsAction(ProjectAction action, Node *node) const const FolderNode *folderNode = this; const QmakeProFileNode *proFileNode; - while (!(proFileNode = dynamic_cast(folderNode))) + while (!(proFileNode = dynamic_cast(folderNode))) { folderNode = folderNode->parentFolderNode(); - Q_ASSERT(proFileNode); + QTC_ASSERT(folderNode, return false); + } + QTC_ASSERT(proFileNode, return false); const QmakeProFile *pro = proFileNode->proFile(); switch (pro ? pro->projectType() : ProjectType::Invalid) { diff --git a/src/plugins/qmakeprojectmanager/qmakenodetreebuilder.cpp b/src/plugins/qmakeprojectmanager/qmakenodetreebuilder.cpp index 87b391d7ba2..abe1b3545b6 100644 --- a/src/plugins/qmakeprojectmanager/qmakenodetreebuilder.cpp +++ b/src/plugins/qmakeprojectmanager/qmakenodetreebuilder.cpp @@ -204,7 +204,7 @@ QmakeProFileNode *QmakeNodeTreeBuilder::buildTree(QmakeProject *project) { // Remove qmake implementation details that litter up the project data: Target *t = project->activeTarget(); - Kit *k = t ? t->kit() : nullptr; + Kit *k = t ? t->kit() : KitManager::defaultKit(); BaseQtVersion *qt = k ? QtKitInformation::qtVersion(k) : nullptr; const FileNameList toExclude = qt ? qt->directoriesToIgnoreInProjectTree() : FileNameList(); diff --git a/src/plugins/qmakeprojectmanager/qmakeproject.cpp b/src/plugins/qmakeprojectmanager/qmakeproject.cpp index abedb874033..c7ff2a2765f 100644 --- a/src/plugins/qmakeprojectmanager/qmakeproject.cpp +++ b/src/plugins/qmakeprojectmanager/qmakeproject.cpp @@ -611,6 +611,7 @@ QStringList QmakeProject::filesGeneratedFrom(const QString &input) const if (const FileNode *file = fileNodeOf(rootProjectNode(), FileName::fromString(input))) { const QmakeProFileNode *pro = static_cast(file->parentFolderNode()); + QTC_ASSERT(pro, return {}); if (const QmakeProFile *proFile = pro->proFile()) return Utils::transform(proFile->generatedFiles(FileName::fromString(pro->buildDir()), file->filePath(), file->fileType()), diff --git a/src/plugins/qmlprofiler/qml/QmlProfilerFlameGraphView.qml b/src/plugins/qmlprofiler/qml/QmlProfilerFlameGraphView.qml index 88f4eb133f7..2de3ec9422c 100644 --- a/src/plugins/qmlprofiler/qml/QmlProfilerFlameGraphView.qml +++ b/src/plugins/qmlprofiler/qml/QmlProfilerFlameGraphView.qml @@ -147,8 +147,14 @@ ScrollView { } onMouseExited: { - if (tooltip.hoveredNode === flamegraphItem) + if (tooltip.hoveredNode === flamegraphItem) { + // Keep the window around until something else is hovered or selected. + if (tooltip.selectedNode === null + || tooltip.selectedNode.typeId !== root.selectedTypeId) { + tooltip.selectedNode = flamegraphItem; + } tooltip.hoveredNode = null; + } } onClicked: { diff --git a/src/plugins/qmlprofiler/qmlprofilertraceview.cpp b/src/plugins/qmlprofiler/qmlprofilertraceview.cpp index 22fad39df91..8519d124223 100644 --- a/src/plugins/qmlprofiler/qmlprofilertraceview.cpp +++ b/src/plugins/qmlprofiler/qmlprofilertraceview.cpp @@ -114,6 +114,8 @@ QmlProfilerTraceView::QmlProfilerTraceView(QWidget *parent, QmlProfilerViewManag break; case QmlProfilerModelManager::ClearingData: d->m_zoomControl->clear(); + if (!d->m_suspendedModels.isEmpty()) + break; // Models are suspended already. AcquiringData was aborted. // Fall through case QmlProfilerModelManager::AcquiringData: // Temporarily remove the models, while we're changing them diff --git a/src/plugins/resourceeditor/resourceeditorplugin.cpp b/src/plugins/resourceeditor/resourceeditorplugin.cpp index 42a59226b73..75cce175429 100644 --- a/src/plugins/resourceeditor/resourceeditorplugin.cpp +++ b/src/plugins/resourceeditor/resourceeditorplugin.cpp @@ -287,6 +287,7 @@ void ResourceEditorPlugin::removeFileContextMenu() QTC_ASSERT(rfn, return); QString path = rfn->filePath().toString(); FolderNode *parent = rfn->parentFolderNode(); + QTC_ASSERT(parent, return); if (!parent->removeFiles(QStringList() << path)) QMessageBox::warning(Core::ICore::mainWindow(), tr("File Removal Failed"), diff --git a/src/plugins/resourceeditor/resourcenode.cpp b/src/plugins/resourceeditor/resourcenode.cpp index b8fbcc10cb2..20f67b2eecd 100644 --- a/src/plugins/resourceeditor/resourcenode.cpp +++ b/src/plugins/resourceeditor/resourcenode.cpp @@ -70,8 +70,9 @@ public: { if (type == TypePermissions) return true; - auto newNode = new ResourceTopLevelNode(m_node->filePath(), false, m_node->contents(), - m_node->parentFolderNode()); + FolderNode *parent = m_node->parentFolderNode(); + QTC_ASSERT(parent, return false); + auto newNode = new ResourceTopLevelNode(m_node->filePath(), false, m_node->contents(), parent); m_node->parentFolderNode()->replaceSubtree(m_node, newNode); return true; } diff --git a/src/shared/qbs b/src/shared/qbs index 512704a5285..13089719966 160000 --- a/src/shared/qbs +++ b/src/shared/qbs @@ -1 +1 @@ -Subproject commit 512704a52858688366a99d8959bf75ee35099e19 +Subproject commit 130897199664f52d737ad4f3e24df19ccfbdee93 diff --git a/tests/system/objects.map b/tests/system/objects.map index fe5a4ea296e..e855d701b52 100644 --- a/tests/system/objects.map +++ b/tests/system/objects.map @@ -212,6 +212,7 @@ :popupFrame_Proposal_QListView {container=':popupFrame_TextEditor::GenericProposalWidget' type='QListView' unnamed='1' visible='1'} :popupFrame_TextEditor::GenericProposalWidget {name='m_popupFrame' type='TextEditor::GenericProposalWidget' visible='1'} :projectComboBox_QComboBox {buddy=':New Text File.Add to project:_QLabel' name='projectComboBox' type='QComboBox' visible='1'} +:projectComboBox_Utils::TreeViewComboBox {buddy=':New Text File.Add to project:_QLabel' name='projectComboBox' type='Utils::TreeViewComboBox' visible='1'} :qdesigner_internal::WidgetBoxCategoryListView {container=':Widget Box_qdesigner_internal::WidgetBoxTreeWidget' occurrence='3' type='qdesigner_internal::WidgetBoxCategoryListView' unnamed='1' visible='1'} :qmakeCallEdit {container=':Qt Creator.scrollArea_QScrollArea' text?='qmake: qmake*' type='QLabel' unnamed='1' visible='1'} :qt_tabwidget_stackedwidget.Core__Internal__GeneralSettings_QWidget {container=':Options.qt_tabwidget_stackedwidget_QStackedWidget' name='Core__Internal__GeneralSettings' type='QWidget' visible='1'} diff --git a/tests/system/shared/project.py b/tests/system/shared/project.py index fa03531e720..d3f47b73e51 100644 --- a/tests/system/shared/project.py +++ b/tests/system/shared/project.py @@ -749,13 +749,14 @@ def compareProjectTree(rootObject, dataset): # creates C++ file(s) and adds them to the current project if one is open # name name of the created object: filename for files, classname for classes # template "C++ Class", "C++ Header File" or "C++ Source File" +# projectName None or name of open project that the files will be added to # forceOverwrite bool: force overwriting existing files? # addToVCS name of VCS to add the file(s) to # newBasePath path to create the file(s) at # expectedSourceName expected name of created source file # expectedHeaderName expected name of created header file -def addCPlusPlusFileToCurrentProject(name, template, forceOverwrite=False, addToVCS="", - newBasePath=None, expectedSourceName=None, expectedHeaderName=None): +def addCPlusPlusFile(name, template, projectName, forceOverwrite=False, addToVCS="", + newBasePath=None, expectedSourceName=None, expectedHeaderName=None): if name == None: test.fatal("File must have a name - got None.") return @@ -785,6 +786,14 @@ def addCPlusPlusFileToCurrentProject(name, template, forceOverwrite=False, addTo test.compare(str(waitForObject("{name='HdrFileName' type='QLineEdit' visible='1'}").text), expectedHeaderName) clickButton(waitForObject(":Next_QPushButton")) + projectComboBox = waitForObjectExists(":projectComboBox_Utils::TreeViewComboBox") + test.compare(projectComboBox.enabled, projectName != None, + "Project combo box must be enabled when a project is open") + projectNameToDisplay = "" + if projectName: + projectNameToDisplay = projectName + test.compare(str(projectComboBox.currentText), projectNameToDisplay, + "The right project must be selected") fileExistedBefore = False if template == "C++ Class": fileExistedBefore = (os.path.exists(os.path.join(basePath, name.lower() + ".cpp")) diff --git a/tests/system/shared/project_explorer.py b/tests/system/shared/project_explorer.py index 2396bbc80f1..686d5722e25 100644 --- a/tests/system/shared/project_explorer.py +++ b/tests/system/shared/project_explorer.py @@ -100,7 +100,9 @@ def switchToBuildOrRunSettingsFor(targetCount, currentTarget, projectSettings): if not test.verify(not str(findObject(currentTargetIndex).toolTip).startswith(clickToActivate), "Verifying target '%s' is enabled." % targets[currentTarget]): return False - mouseClick(waitForObject(currentTargetIndex)) + index = waitForObject(currentTargetIndex) + treeView.scrollTo(index) + mouseClick(index) if projectSettings == ProjectSettings.BUILD: settingsIndex = getQModelIndexStr("text='Build'", currentTargetIndex) diff --git a/tests/system/suite_HELP/tst_HELP02/test.py b/tests/system/suite_HELP/tst_HELP02/test.py index 4f59878a14d..f246a41b6c6 100755 --- a/tests/system/suite_HELP/tst_HELP02/test.py +++ b/tests/system/suite_HELP/tst_HELP02/test.py @@ -27,7 +27,7 @@ source("../../shared/qtcreator.py") # test Qt Creator version information from file and dialog def getQtCreatorVersionFromDialog(): - chk = re.search("(?<=Qt Creator)\s\d+.\d+.\d+\S*", + chk = re.search("(?<=Qt Creator)\s\d+.\d+.\d+[-\w]*", str(waitForObject("{text?='*Qt Creator*' type='QLabel' unnamed='1' visible='1' " "window=':About Qt Creator_Core::Internal::VersionDialog'}").text)) try: diff --git a/tests/system/suite_editors/tst_rename_macros/test.py b/tests/system/suite_editors/tst_rename_macros/test.py index 067831da7d8..581247bfdfb 100644 --- a/tests/system/suite_editors/tst_rename_macros/test.py +++ b/tests/system/suite_editors/tst_rename_macros/test.py @@ -42,8 +42,8 @@ def main(): if not testRenameMacroAfterSourceModification(): return headerName = "anothertestfile.h" - addCPlusPlusFileToCurrentProject(headerName, "C++ Header File", - expectedHeaderName=headerName) + addCPlusPlusFile(headerName, "C++ Header File", "testfiles.pro", + expectedHeaderName=headerName) if not testRenameMacroAfterSourceMoving(): return invokeMenuItem("File", "Save All") diff --git a/tests/system/suite_general/tst_new_class/test.py b/tests/system/suite_general/tst_new_class/test.py index d7b37abddcd..7f1f056908b 100644 --- a/tests/system/suite_general/tst_new_class/test.py +++ b/tests/system/suite_general/tst_new_class/test.py @@ -34,9 +34,9 @@ def main(): startApplication("qtcreator" + SettingsPath) if not startedWithoutPluginError(): return - addCPlusPlusFileToCurrentProject(newClassName, "C++ Class", newBasePath=basePath, - expectedSourceName=sourceFileName, - expectedHeaderName=headerFileName) + addCPlusPlusFile(newClassName, "C++ Class", None, newBasePath=basePath, + expectedSourceName=sourceFileName, + expectedHeaderName=headerFileName) mainWindow = waitForObject(":Qt Creator_Core::Internal::MainWindow") if test.verify(waitFor("sourceFileName in str(mainWindow.windowTitle)", 1000), @@ -77,17 +77,17 @@ def main(): def overwritten(filename): return notOverwrittenComment not in readFile(os.path.join(basePath, filename)) - addCPlusPlusFileToCurrentProject(newClassName, "C++ Class", False, newBasePath=basePath, - expectedSourceName=sourceFileName, - expectedHeaderName=headerFileName) + addCPlusPlusFile(newClassName, "C++ Class", None, False, + newBasePath=basePath, expectedSourceName=sourceFileName, + expectedHeaderName=headerFileName) test.verify(not waitFor("overwritten(sourceFileName)", 2000), "Source file should not be overwritten.") test.verify(not waitFor("overwritten(headerFileName)", 500), "Header file should not be overwritten.") - addCPlusPlusFileToCurrentProject(newClassName, "C++ Class", True, newBasePath=basePath, - expectedSourceName=sourceFileName, - expectedHeaderName=headerFileName) + addCPlusPlusFile(newClassName, "C++ Class", None, True, + newBasePath=basePath, expectedSourceName=sourceFileName, + expectedHeaderName=headerFileName) test.verify(waitFor("overwritten(sourceFileName)", 2000), "Source file should be overwritten.") test.verify(waitFor("overwritten(headerFileName)", 500), diff --git a/tests/system/suite_general/tst_opencreator_qbs/test.py b/tests/system/suite_general/tst_opencreator_qbs/test.py index 51b6b36185e..05167f53b3b 100644 --- a/tests/system/suite_general/tst_opencreator_qbs/test.py +++ b/tests/system/suite_general/tst_opencreator_qbs/test.py @@ -43,8 +43,8 @@ def main(): return test.log("Start parsing project") rootNodeTemplate = "{column='0' container=':Qt Creator_Utils::NavigationTreeView' text~='%s( \[\S+\])?' type='QModelIndex'}" - ntwObject = waitForObject(rootNodeTemplate % "qtcreator.qbs") - if waitFor("ntwObject.model().rowCount(ntwObject) > 2", 200000): # No need to wait for C++-parsing + ntwObject = waitForObject(rootNodeTemplate % "Qt Creator", 200000) + if waitFor("ntwObject.model().rowCount(ntwObject) > 2", 20000): # No need to wait for C++-parsing test.log("Parsing project done") # we only need the project else: test.warning("Parsing project timed out") diff --git a/tests/system/suite_tools/tst_git_local/test.py b/tests/system/suite_tools/tst_git_local/test.py index eda76fea5c7..a9186a228f1 100644 --- a/tests/system/suite_tools/tst_git_local/test.py +++ b/tests/system/suite_tools/tst_git_local/test.py @@ -175,8 +175,8 @@ def main(): commitMessages = [commit("Initial Commit", "Committed 5 file(s).")] clickButton(waitForObject(":*Qt Creator.Clear_QToolButton")) headerName = "pointless_header.h" - addCPlusPlusFileToCurrentProject(headerName, "C++ Header File", addToVCS="Git", - expectedHeaderName=headerName) + addCPlusPlusFile(headerName, "C++ Header File", projectName + ".pro", + addToVCS="Git", expectedHeaderName=headerName) commitMessages.insert(0, commit("Added pointless header file", "Committed 2 file(s).")) readmeName = "README.txt" addEmptyFileOutsideProject(readmeName)