From 9c8400d961f765608feb94b18b614a6cb3fd57ec Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Mon, 30 Sep 2019 09:57:40 +0200 Subject: [PATCH 1/6] Output windows: Skip filter function if no filter is set Running the filter function is (too?) expensive, so make sure that's only done when there actually is a filter. Task-number: QTCREATORBUG-22914 Change-Id: Ie96a4e20ebb10c08d83e75641e70b42b13377b22 Reviewed-by: Eike Ziller --- src/plugins/coreplugin/outputwindow.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/plugins/coreplugin/outputwindow.cpp b/src/plugins/coreplugin/outputwindow.cpp index 6c33b8dafe2..f920ffc3891 100644 --- a/src/plugins/coreplugin/outputwindow.cpp +++ b/src/plugins/coreplugin/outputwindow.cpp @@ -117,7 +117,10 @@ OutputWindow::OutputWindow(Context context, const QString &settingsKey, QWidget connect(copyAction, &QAction::triggered, this, &QPlainTextEdit::copy); connect(pasteAction, &QAction::triggered, this, &QPlainTextEdit::paste); connect(selectAllAction, &QAction::triggered, this, &QPlainTextEdit::selectAll); - connect(this, &QPlainTextEdit::blockCountChanged, this, &OutputWindow::filterNewContent); + connect(this, &QPlainTextEdit::blockCountChanged, this, [this] { + if (!d->filterText.isEmpty()) + filterNewContent(); + }); connect(this, &QPlainTextEdit::undoAvailable, undoAction, &QAction::setEnabled); connect(this, &QPlainTextEdit::redoAvailable, redoAction, &QAction::setEnabled); From 17f5e19399151a090b177681d9cfe606e71010c2 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Fri, 16 Aug 2019 08:36:52 +0200 Subject: [PATCH 2/6] Squish: Stabilize tests that rely on a parsed project As more and more progress bars might be present for different purposes and we are not able to easily distinguish them we need to use a more reliable way to wait for the end of parsing a project. Add a respective function and use the new approach where this appears to be appropriate or necessary. Change-Id: I20e2b9b0efd4785f8f0b1ddbc8496be111628669 Reviewed-by: Robert Loehning --- tests/system/shared/project.py | 9 +++++++++ tests/system/suite_CSUP/tst_CSUP04/test.py | 2 +- tests/system/suite_CSUP/tst_CSUP05/test.py | 2 +- tests/system/suite_WELP/tst_WELP02/test.py | 2 +- tests/system/suite_editors/tst_basic_cpp_support/test.py | 2 +- tests/system/suite_general/tst_build_speedcrunch/test.py | 2 +- tests/system/suite_general/tst_cmake_speedcrunch/test.py | 2 +- tests/system/suite_general/tst_rename_file/test.py | 4 ++-- tests/system/suite_general/tst_session_handling/test.py | 2 +- tests/system/suite_qtquick/tst_qtquick_creation4/test.py | 2 +- 10 files changed, 19 insertions(+), 10 deletions(-) diff --git a/tests/system/shared/project.py b/tests/system/shared/project.py index 2337f4fc4ff..08398f14fab 100644 --- a/tests/system/shared/project.py +++ b/tests/system/shared/project.py @@ -662,3 +662,12 @@ def addCPlusPlusFile(name, template, projectName, forceOverwrite=False, addToVCS buttonToClick = 'Cancel' clickButton("{text='%s' type='QPushButton' unnamed='1' visible='1' window=%s}" % (buttonToClick, overwriteDialog)) + +# if one of the parameters is set to 0 or below the respective parsing won't be waited for +def waitForProjectParsing(projectParsingTimeout=10000, codemodelParsingTimeout=10000): + if projectParsingTimeout > 0: + runButton = findObject(':*Qt Creator.Run_Core::Internal::FancyToolButton') + # Wait for parsing to complete + waitFor("runButton.enabled", projectParsingTimeout) + if codemodelParsingTimeout > 0: + progressBarWait(codemodelParsingTimeout) diff --git a/tests/system/suite_CSUP/tst_CSUP04/test.py b/tests/system/suite_CSUP/tst_CSUP04/test.py index 196d25bc1d8..143e3fe8126 100644 --- a/tests/system/suite_CSUP/tst_CSUP04/test.py +++ b/tests/system/suite_CSUP/tst_CSUP04/test.py @@ -44,7 +44,7 @@ def main(): # open example project openQmakeProject(examplePath) # wait for parsing to complete - progressBarWait(30000) + waitForProjectParsing() checkCodeModelSettings(useClang) # open .cpp file in editor if not openDocument("openglwindow.Sources.main\\.cpp"): diff --git a/tests/system/suite_CSUP/tst_CSUP05/test.py b/tests/system/suite_CSUP/tst_CSUP05/test.py index c9f3cb892d1..3e686b0509a 100644 --- a/tests/system/suite_CSUP/tst_CSUP05/test.py +++ b/tests/system/suite_CSUP/tst_CSUP05/test.py @@ -43,7 +43,7 @@ def main(): # open example project openQmakeProject(examplePath) # wait for parsing to complete - progressBarWait(30000) + waitForProjectParsing() checkCodeModelSettings(useClang) # open .cpp file in editor if not openDocument("openglwindow.Sources.main\\.cpp"): diff --git a/tests/system/suite_WELP/tst_WELP02/test.py b/tests/system/suite_WELP/tst_WELP02/test.py index 7fe8b3d4648..b44f0382dce 100644 --- a/tests/system/suite_WELP/tst_WELP02/test.py +++ b/tests/system/suite_WELP/tst_WELP02/test.py @@ -99,7 +99,7 @@ def main(): # select "Open project" and select a project examplePath = os.path.join(prepareTemplate(sourceExample), "animation.pro") openQmakeProject(examplePath, fromWelcome = True) - progressBarWait(30000) + waitForProjectParsing() test.verify(checkIfObjectExists("{column='0' container=':Qt Creator_Utils::NavigationTreeView'" " text~='animation( \(.*\))?' type='QModelIndex'}"), "Verifying: The project is opened in 'Edit' mode after configuring.") diff --git a/tests/system/suite_editors/tst_basic_cpp_support/test.py b/tests/system/suite_editors/tst_basic_cpp_support/test.py index 69e43adf7fe..425512c4c7c 100644 --- a/tests/system/suite_editors/tst_basic_cpp_support/test.py +++ b/tests/system/suite_editors/tst_basic_cpp_support/test.py @@ -42,7 +42,7 @@ def main(): if not startedWithoutPluginError(): return openQmakeProject(proFile) - progressBarWait(20000) + waitForProjectParsing() selectFromLocator("dummy.cpp") ## Waiting for a solution from Froglogic to make the below work. diff --git a/tests/system/suite_general/tst_build_speedcrunch/test.py b/tests/system/suite_general/tst_build_speedcrunch/test.py index 32a132ad639..e3543d55fae 100644 --- a/tests/system/suite_general/tst_build_speedcrunch/test.py +++ b/tests/system/suite_general/tst_build_speedcrunch/test.py @@ -42,7 +42,7 @@ def main(): if not startedWithoutPluginError(): return openQmakeProject(SpeedCrunchPath, [Targets.DESKTOP_4_8_7_DEFAULT]) - progressBarWait(30000) + waitForProjectParsing() fancyToolButton = waitForObject(":*Qt Creator_Core::Internal::FancyToolButton") diff --git a/tests/system/suite_general/tst_cmake_speedcrunch/test.py b/tests/system/suite_general/tst_cmake_speedcrunch/test.py index afc196abb8e..2d9a3e2defd 100644 --- a/tests/system/suite_general/tst_cmake_speedcrunch/test.py +++ b/tests/system/suite_general/tst_cmake_speedcrunch/test.py @@ -60,7 +60,7 @@ def main(): test.fatal("Could not open/create cmake project - leaving test") invokeMenuItem("File", "Exit") return - progressBarWait(30000) + waitForProjectParsing() naviTreeView = "{column='0' container=':Qt Creator_Utils::NavigationTreeView' text~='%s' type='QModelIndex'}" if cmakeSupportsServerMode(): treeFile = "projecttree_speedcrunch_server.tsv" diff --git a/tests/system/suite_general/tst_rename_file/test.py b/tests/system/suite_general/tst_rename_file/test.py index 9d46be1d37f..cb5d434fe15 100644 --- a/tests/system/suite_general/tst_rename_file/test.py +++ b/tests/system/suite_general/tst_rename_file/test.py @@ -46,7 +46,7 @@ def main(): "OTHER_FILES += example.qml") invokeMenuItem("File", "Save All") invokeMenuItem("File", "Close All") - progressBarWait() + waitForProjectParsing() for filetype, filename in [["Headers", "person.h"], ["Sources", "main.cpp"], ["Sources", "person.cpp"], @@ -66,7 +66,7 @@ def main(): renameFile(templateDir, usedProFile, projectName + "." + tempFiletype, previous, filename) # QTCREATORBUG-13176 does update the navigator async - progressBarWait() + waitForProjectParsing() if filetype == "Headers": verifyRenamedIncludes(templateDir, "main.cpp", previous, filename) verifyRenamedIncludes(templateDir, "person.cpp", previous, filename) diff --git a/tests/system/suite_general/tst_session_handling/test.py b/tests/system/suite_general/tst_session_handling/test.py index 3a536975f2e..702273b265f 100644 --- a/tests/system/suite_general/tst_session_handling/test.py +++ b/tests/system/suite_general/tst_session_handling/test.py @@ -40,7 +40,7 @@ def main(): checkWelcomePage(sessionName, True) for project in projects: openQmakeProject(project, [Targets.DESKTOP_5_6_1_DEFAULT]) - progressBarWait(20000) + waitForProjectParsing() checkNavigator(52, "Verifying whether all projects have been opened.") openDocument("animation.Resources.animation\\.qrc./animation.basics.animators\\.qml") openDocument("keyinteraction.Sources.main\\.cpp") diff --git a/tests/system/suite_qtquick/tst_qtquick_creation4/test.py b/tests/system/suite_qtquick/tst_qtquick_creation4/test.py index 58ef85e3331..c1e5105ba1a 100644 --- a/tests/system/suite_qtquick/tst_qtquick_creation4/test.py +++ b/tests/system/suite_qtquick/tst_qtquick_creation4/test.py @@ -33,7 +33,7 @@ def main(): # using a temporary directory won't mess up a potentially existing createNewQmlExtension(tempDir(), [target]) # wait for parsing to complete - progressBarWait(30000) + waitForProjectParsing() test.log("Building project Qt Quick 2 Extension Plugin (%s)" % Targets.getStringForTarget(target)) invokeMenuItem("Build","Build All") From 85fcd10f90e3ccf8e8c5586fd84161145ef862a0 Mon Sep 17 00:00:00 2001 From: Elvis Angelaccio Date: Wed, 19 Jul 2017 19:27:47 +0200 Subject: [PATCH 3/6] Show application icon in Plasma Wayland sessions kwin_wayland fetches application icons from .desktop files, so we need to set the desktop filename on the QGuiApplication instance (otherwise kwin will set a generic wayland icon as fallback). Change-Id: I89921ace4a5a4ff2a2387111e51a8914f58e44a8 Reviewed-by: Eike Ziller --- src/app/main.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/app/main.cpp b/src/app/main.cpp index 55ade018714..270902c5494 100644 --- a/src/app/main.cpp +++ b/src/app/main.cpp @@ -523,6 +523,8 @@ int main(int argc, char **argv) } } + app.setDesktopFileName("org.qt-project.qtcreator.desktop"); + // Make sure we honor the system's proxy settings QNetworkProxyFactory::setUseSystemConfiguration(true); From 736eef24ca9263339f4c576cba5d4b20fe188045 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Tue, 24 Sep 2019 14:39:50 +0200 Subject: [PATCH 4/6] Designer: Fix look-up of resources for UI files Commit 81a643ec99, fixing QTCREATORBUG-22412, was too restrictive: UI files in applications have access to resources of library dependencies, so we must consider those. We now only exclude resources from other applications. Note that this will potentially list non-applicable resources, e.g. those from libraries to which our product does not have access. This cannot be reasonably prevented, because not all build systems provide this information. It's also not as bad as missing resources. Fixes: QTCREATORBUG-22909 Fixes: QTCREATORBUG-22962 Change-Id: I51a87402b43c156618982813c408060f300e4e58 Reviewed-by: hjk --- .../cmakeprojectmanager/cmakeprojectnodes.cpp | 2 +- src/plugins/designer/resourcehandler.cpp | 33 ++++++++++++------- src/plugins/projectexplorer/projectnodes.h | 9 +++-- src/plugins/qbsprojectmanager/qbsnodes.cpp | 9 ++++- .../qmakeprojectmanager/qmakenodes.cpp | 9 ++++- 5 files changed, 45 insertions(+), 17 deletions(-) diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectnodes.cpp b/src/plugins/cmakeprojectmanager/cmakeprojectnodes.cpp index f14f627b34f..deb00e8f95d 100644 --- a/src/plugins/cmakeprojectmanager/cmakeprojectnodes.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeprojectnodes.cpp @@ -173,7 +173,7 @@ CMakeTargetNode::CMakeTargetNode(const Utils::FilePath &directory, const QString setPriority(Node::DefaultProjectPriority + 900); setIcon(QIcon(":/projectexplorer/images/build.png")); // TODO: Use proper icon! setListInProject(false); - setIsProduct(); + setProductType(ProductType::Other); } QString CMakeTargetNode::generateId(const Utils::FilePath &directory, const QString &target) diff --git a/src/plugins/designer/resourcehandler.cpp b/src/plugins/designer/resourcehandler.cpp index 84020f77ee4..c01dbc95f6d 100644 --- a/src/plugins/designer/resourcehandler.cpp +++ b/src/plugins/designer/resourcehandler.cpp @@ -99,26 +99,37 @@ void ResourceHandler::updateResourcesHelper(bool updateProjectResources) // Find the (sub-)project the file belongs to. We don't want to find resources // from other parts of the project tree, e.g. via a qmake subdirs project. - ProjectNode *projectNode = project->rootProjectNode(); - Node * const fileNode = projectNode->findNode([&fileName](const Node *n) { + Node * const fileNode = project->rootProjectNode()->findNode([&fileName](const Node *n) { return n->filePath().toString() == fileName; }); + ProjectNode *projectNodeForUiFile = nullptr; if (fileNode) { // We do not want qbs groups or qmake .pri files here, as they contain only a subset // of the relevant files. - projectNode = fileNode->parentProjectNode(); - while (projectNode && !projectNode->isProduct()) - projectNode = projectNode->parentProjectNode(); + projectNodeForUiFile = fileNode->parentProjectNode(); + while (projectNodeForUiFile && !projectNodeForUiFile->isProduct()) + projectNodeForUiFile = projectNodeForUiFile->parentProjectNode(); } - if (!projectNode) - projectNode = project->rootProjectNode(); + if (!projectNodeForUiFile) + projectNodeForUiFile = project->rootProjectNode(); + + const auto useQrcFile = [projectNodeForUiFile, project](const Node *qrcNode) { + if (projectNodeForUiFile == project->rootProjectNode()) + return true; + ProjectNode *projectNodeForQrcFile = qrcNode->parentProjectNode(); + while (projectNodeForQrcFile && !projectNodeForQrcFile->isProduct()) + projectNodeForQrcFile = projectNodeForQrcFile->parentProjectNode(); + return !projectNodeForQrcFile + || projectNodeForQrcFile == projectNodeForUiFile + || projectNodeForQrcFile->productType() != ProductType::App; + }; QStringList projectQrcFiles; - projectNode->forEachNode([&](FileNode *node) { - if (node->fileType() == FileType::Resource) + project->rootProjectNode()->forEachNode([&](FileNode *node) { + if (node->fileType() == FileType::Resource && useQrcFile(node)) projectQrcFiles.append(node->filePath().toString()); }, [&](FolderNode *node) { - if (dynamic_cast(node)) + if (dynamic_cast(node) && useQrcFile(node)) projectQrcFiles.append(node->filePath().toString()); }); // Check if the user has chosen to update the lacking resource inside designer @@ -130,7 +141,7 @@ void ResourceHandler::updateResourcesHelper(bool updateProjectResources) } if (!qrcPathsToBeAdded.isEmpty()) { m_handlingResources = true; - projectNode->addFiles(qrcPathsToBeAdded); + projectNodeForUiFile->addFiles(qrcPathsToBeAdded); m_handlingResources = false; projectQrcFiles += qrcPathsToBeAdded; } diff --git a/src/plugins/projectexplorer/projectnodes.h b/src/plugins/projectexplorer/projectnodes.h index ce36882aa9c..a214407515e 100644 --- a/src/plugins/projectexplorer/projectnodes.h +++ b/src/plugins/projectexplorer/projectnodes.h @@ -57,6 +57,8 @@ enum class FileType : quint16 { FileTypeSize }; +enum class ProductType { App, Lib, Other, None }; + enum ProjectAction { // Special value to indicate that the actions are handled by the parent InheritedFromParent, @@ -357,15 +359,16 @@ public: virtual QVariant data(Core::Id role) const; virtual bool setData(Core::Id role, const QVariant &value) const; - bool isProduct() const { return m_isProduct; } + bool isProduct() const { return m_productType != ProductType::None; } + ProductType productType() const { return m_productType; } protected: - void setIsProduct() { m_isProduct = true; } + void setProductType(ProductType type) { m_productType = type; } QString m_target; private: - bool m_isProduct = false; + ProductType m_productType = ProductType::None; }; class PROJECTEXPLORER_EXPORT ContainerNode : public FolderNode diff --git a/src/plugins/qbsprojectmanager/qbsnodes.cpp b/src/plugins/qbsprojectmanager/qbsnodes.cpp index 62762069b2a..4f7f2e5f086 100644 --- a/src/plugins/qbsprojectmanager/qbsnodes.cpp +++ b/src/plugins/qbsprojectmanager/qbsnodes.cpp @@ -320,7 +320,14 @@ QbsProductNode::QbsProductNode(const qbs::ProductData &prd) : { static QIcon productIcon = Core::FileIconProvider::directoryIcon(Constants::QBS_PRODUCT_OVERLAY_ICON); setIcon(productIcon); - setIsProduct(); + if (m_qbsProductData.isRunnable()) { + setProductType(ProductType::App); + } else if (m_qbsProductData.type().contains("dynamiclibrary") + || m_qbsProductData.type().contains("staticlibrary")) { + setProductType(ProductType::Lib); + } else { + setProductType(ProductType::Other); + } } bool QbsProductNode::supportsAction(ProjectAction action, const Node *node) const diff --git a/src/plugins/qmakeprojectmanager/qmakenodes.cpp b/src/plugins/qmakeprojectmanager/qmakenodes.cpp index a71ab8c3d6a..24b6b8cb038 100644 --- a/src/plugins/qmakeprojectmanager/qmakenodes.cpp +++ b/src/plugins/qmakeprojectmanager/qmakenodes.cpp @@ -230,7 +230,14 @@ FolderNode::AddNewInformation QmakePriFileNode::addNewInformation(const QStringL QmakeProFileNode::QmakeProFileNode(QmakeProject *project, const FilePath &filePath, QmakeProFile *pf) : QmakePriFileNode(project, this, filePath, pf) { - setIsProduct(); + if (projectType() == ProjectType::ApplicationTemplate) { + setProductType(ProductType::App); + } else if (projectType() == ProjectType::SharedLibraryTemplate + || projectType() == ProjectType::StaticLibraryTemplate) { + setProductType(ProductType::Lib); + } else if (projectType() != ProjectType::SubDirsTemplate) { + setProductType(ProductType::Other); + } } bool QmakeProFileNode::showInSimpleTree() const From 0907bc8658fdb82efdaa07013ae164642856938a Mon Sep 17 00:00:00 2001 From: Alexander Akulich Date: Fri, 27 Sep 2019 18:25:50 +0300 Subject: [PATCH 5/6] CMake Build: Fix LLVM lookup for cases when many versions available If calling both find_package(Clang) and find_package(LLVM), call find_package(Clang) first to get the currently active Clang version by default with a consistent version of LLVM. (Similar to the FindPythonInterp/PythonLibs ordering) Change-Id: Ib6da04e0fb0ffc1fe67a8eafb0c5f04abbb36b6c Reviewed-by: Cristian Adam Reviewed-by: Tobias Hunger --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 41278e8d934..a967375571c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -97,8 +97,8 @@ else() endif() install(TARGETS OptionalSvg EXPORT QtCreator) -find_package(LLVM QUIET) find_package(Clang COMPONENTS libclang QUIET) +find_package(LLVM QUIET) if (APPLE) find_library(FWCoreFoundation CoreFoundation) From 312ff692b02d6b19f39303591c7dc0156bf46661 Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 1 Oct 2019 16:36:42 +0200 Subject: [PATCH 6/6] Debugger: Do not crash when displaying uninitialized QImages Fixes: QTCREATORBUG-23031 Change-Id: I074cdaf509edac6e5659d2e976ed7188e8944d81 Reviewed-by: Mitch Curtis Reviewed-by: Eike Ziller --- src/plugins/debugger/watchhandler.cpp | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/src/plugins/debugger/watchhandler.cpp b/src/plugins/debugger/watchhandler.cpp index 9eccfbdb1eb..66d73e84bf9 100644 --- a/src/plugins/debugger/watchhandler.cpp +++ b/src/plugins/debugger/watchhandler.cpp @@ -2296,15 +2296,20 @@ void WatchModel::showEditValue(const WatchItem *item) QTC_ASSERT(0 < nbytes && nbytes < 10000 * 10000, return); QTC_ASSERT(0 < imformat && imformat < 32, return); QImage im(width, height, QImage::Format(imformat)); - std::memcpy(im.bits(), bits, nbytes); - auto v = m_separatedView->prepareObject(item); - v->setInfo(item->address ? - tr("%1 Object at %2").arg(item->type, item->hexAddress()) : - tr("%1 Object at Unknown Address").arg(item->type) + " " + - ImageViewer::tr("Size: %1x%2, %3 byte, format: %4, depth: %5") - .arg(width).arg(height).arg(nbytes).arg(im.format()).arg(im.depth()) - ); - v->setImage(im); + const qsizetype size = im.sizeInBytes(); + // If our computation of image size doesn't fit the client's + // chances are that we can't properly display it either. + if (size == nbytes) { + std::memcpy(im.bits(), bits, nbytes); + auto v = m_separatedView->prepareObject(item); + v->setInfo(item->address ? + tr("%1 Object at %2").arg(item->type, item->hexAddress()) : + tr("%1 Object at Unknown Address").arg(item->type) + " " + + ImageViewer::tr("Size: %1x%2, %3 byte, format: %4, depth: %5") + .arg(width).arg(height).arg(nbytes).arg(im.format()).arg(im.depth()) + ); + v->setImage(im); + } } else if (format == DisplayLatin1String || format == DisplayUtf8String || format == DisplayUtf16String