diff --git a/README.md b/README.md index 960a50fd4ee..13f9dbda8ee 100644 --- a/README.md +++ b/README.md @@ -277,6 +277,29 @@ http://llvm.org/docs/GettingStarted.html#git-mirror: Qt Creator includes the following third-party components, we thank the authors who made this possible: +### Clazy + + https://github.com/KDE/clazy + + Copyright (C) 2015-2018 Clazy Team + + Distributed under GNU LIBRARY GENERAL PUBLIC LICENSE Version 2 (LGPL2). + + Integrated with patches from QtCreator/dist/clang/patches, see README.md there. + +### LLVM/Clang + + http://llvm.org/svn/llvm-project/llvm + http://llvm.org/svn/llvm-project/cfe/trunk + http://llvm.org/svn/llvm-project/clang-tools-extra/trunk + + Copyright (C) 2003-2018 LLVM Team + + Distributed under the University of Illinois/NCSA Open Source License (NCSA), + see https://github.com/llvm-mirror/llvm/blob/master/LICENSE.TXT + + With additional patches from QtCreator/dist/clang/patches, see README.md there. + ### Reference implementation for std::experimental::optional https://github.com/akrzemi1/Optional diff --git a/dist/changes-4.6.0.md b/dist/changes-4.6.0.md new file mode 100644 index 00000000000..9f1db648bd9 --- /dev/null +++ b/dist/changes-4.6.0.md @@ -0,0 +1,147 @@ +Qt Creator version 4.6 contains bug fixes and new features. + +The most important changes are listed in this document. For a complete +list of changes, see the Git log for the Qt Creator sources that +you can check out from the public Git repository. For example: + + git clone git://code.qt.io/qt-creator/qt-creator.git + git log --cherry-pick --pretty=oneline origin/4.5..v4.6.0 + +General + +* Locator + * Added filter `b` for bookmarks + * Added filter `t` for triggering items from main menu + * Added filter `=` for evaluating JavaScript expressions + (QTCREATORBUG-14380) +* File System View + * Added bread crumbs for file path (QTCREATORBUG-19203) + * Added `Add New`, `Rename`, `Remove File`, `Diff Against Current File` + (QTCREATORBUG-19213, QTCREATORBUG-19209, QTCREATORBUG-19208, + QTCREATORBUG-19211) +* Added restoration of search flags when choosing search term from history + +Editing + +* Added option to display annotations between lines (QTCREATORBUG-19181) +* Fixed that editor could jump to end of file when editing in a different split + (QTCREATORBUG-19550) + +All Projects + +* Added filtering to project kit setup page + +Qbs Projects + +* Added option to add library paths to dependencies (QTCREATORBUG-19274) + +C++ Support + +* Clang Code Model + * Switched to Clang 5.0, adding support for C++17 + * Implemented information tool tips, which improves type information + including resolution of `auto` types (QTCREATORBUG-11259), template arguments + for template types, and the first or `\brief` paragraph of documentation + comments (QTCREATORBUG-4557) + * Integrated Clang-Tidy and Clazy. + Enable checks in Options > C++ > Code Model > Clang Code Model Warnings + * Added separate highlighting for function definitions (QTCREATORBUG-16625) + +QML Support + +* Added inline annotations for issues from code model + +Debugging + +* Split `Expressions` view from `Locals` view (QTCREATORBUG-19167) + +Qt Quick Designer + +* Added font and text properties from Qt 5.10 +* Fixed that items blurred when zooming in +* Fixed crash when changing control focus policy (QTCREATORBUG-19563) + +Version Control Systems + +* Git + * Added `Recover Deleted Files` + * Added `Reload` button to `git log` and `git blame` +* Gerrit + * Added support for private and work-in-progress changes for + Gerrit 2.15 and later + +Diff Viewer + +* Added folding for files and chunks + +Test Integration + +* Added grouping of test cases (QTCREATORBUG-17979) +* Google Test + * Fixed detection of crashed tests (QTCREATORBUG-19565) + +Model Editor + +* Added support for text alignment +* Added support for multi-line object names +* Added support for dragging items onto model editor from more panes +* Added `Export Selected Elements` +* Added `Flat` visual role +* Added `Add Related Elements` to diagram context menu +* Added wizard for scratch models +* Fixed issue with selecting items (QTCREATORBUG-18368) + +Platform Specific + +Windows + +* Added support for the [heob](https://github.com/ssbssa/heob/releases) + memory analyzer +* Fixed detection of CDB in non-default installation roots + +Android + +* Fixed issues with GCC include directories in Clang code model + +Remote Linux + +* Fixed that remote application was not killed before deployment + (QTCREATORBUG-19326) + +Credits for these changes go to: +Adam Treat +Alessandro Portale +Alexandru Croitor +Andre Hartmann +André Pönitz +Christian Gagneraud +Christian Kandeler +Christian Stenger +Daniel Engelke +David Schulz +Eike Ziller +Friedemann Kleint +Hannes Domani +Hugo Holgersson +Ivan Donchevskii +Jake Petroules +Jaroslaw Kobus +Jochen Becher +Jörg Bornemann +Marco Benelli +Marco Bubke +Mitch Curtis +Nikita Baryshnikov +Nikolai Kosjar +Oliver Wolff +Orgad Shaneh +Oswald Buddenhagen +Przemyslaw Gorszkowski +Robert Löhning +Thomas Hartmann +Tim Jenssen +Tobias Hunger +Tomasz Olszak +Tor Arne Vestbø +Ulf Hermann +Vikas Pachdha diff --git a/doc/images/qtcreator-add-resource-wizard2.png b/doc/images/qtcreator-add-resource-wizard2.png index a0c2614b02f..4bf2d9e54fd 100644 Binary files a/doc/images/qtcreator-add-resource-wizard2.png and b/doc/images/qtcreator-add-resource-wizard2.png differ diff --git a/doc/images/qtcreator-add-resource-wizard3.png b/doc/images/qtcreator-add-resource-wizard3.png index cd9e6eb7c2f..6aa138d9969 100644 Binary files a/doc/images/qtcreator-add-resource-wizard3.png and b/doc/images/qtcreator-add-resource-wizard3.png differ diff --git a/doc/images/qtcreator-clang-code-model-options.png b/doc/images/qtcreator-clang-code-model-options.png index c48856a2018..1c35af1fb02 100644 Binary files a/doc/images/qtcreator-clang-code-model-options.png and b/doc/images/qtcreator-clang-code-model-options.png differ diff --git a/doc/images/qtcreator-class-info-qt-gui.png b/doc/images/qtcreator-class-info-qt-gui.png index f3207eeb729..adb7adf6084 100644 Binary files a/doc/images/qtcreator-class-info-qt-gui.png and b/doc/images/qtcreator-class-info-qt-gui.png differ diff --git a/doc/images/qtcreator-filesystem-view.png b/doc/images/qtcreator-filesystem-view.png index cf8f6bb666f..cd730fc925b 100644 Binary files a/doc/images/qtcreator-filesystem-view.png and b/doc/images/qtcreator-filesystem-view.png differ diff --git a/doc/images/qtcreator-intro-and-location-qt-gui.png b/doc/images/qtcreator-intro-and-location-qt-gui.png index dec4933a916..84ece94bc33 100644 Binary files a/doc/images/qtcreator-intro-and-location-qt-gui.png and b/doc/images/qtcreator-intro-and-location-qt-gui.png differ diff --git a/doc/images/qtcreator-new-project-qt-versions-qt-gui.png b/doc/images/qtcreator-new-project-qt-versions-qt-gui.png index 8a1015afde2..c8c83655394 100644 Binary files a/doc/images/qtcreator-new-project-qt-versions-qt-gui.png and b/doc/images/qtcreator-new-project-qt-versions-qt-gui.png differ diff --git a/doc/images/qtcreator-new-project-summary-qt-gui.png b/doc/images/qtcreator-new-project-summary-qt-gui.png index e484cad0d51..70daffe6afa 100644 Binary files a/doc/images/qtcreator-new-project-summary-qt-gui.png and b/doc/images/qtcreator-new-project-summary-qt-gui.png differ diff --git a/doc/src/editors/creator-clang-codemodel.qdoc b/doc/src/editors/creator-clang-codemodel.qdoc index c3e52e6a9b2..673159fd90c 100644 --- a/doc/src/editors/creator-clang-codemodel.qdoc +++ b/doc/src/editors/creator-clang-codemodel.qdoc @@ -75,8 +75,8 @@ useful if the code contains typos, for example. Clang keeps up with the development of the C++ language. At the time of this - writing, it supports C++98/03, C++11, C++14, C89, C99, Objective-C, and - Objective-C++. + writing, it supports C++98/03, C++11, C++14, C++17, C89, C99, Objective-C, + and Objective-C++. On the downside, for large projects using Clang as code model is slower than using the built-in code model. Clang does not need to generate object files, @@ -94,11 +94,27 @@ \li Syntactic and semantic highlighting \li Diagnostics \li Tooltips + \li Clang-Tidy and Clazy checks + \li Renaming of local symbols \endlist To use the plugin, you must activate it and configure it in \QC. + \section1 Using Clang-Tidy and Clazy + + \l{https://clang.llvm.org/extra/clang-tidy/}{Clang-Tidy} and + \l{https://github.com/KDE/clazy/blob/master/README.md}{Clazy} are delivered + as parts of the Clang library delivered with \QC. + + Clang-Tidy provides an extensible framework for diagnosing and fixing + typical programming errors, such as style violations, interface misuse, or + issues that can be found via static analysis. + + Clazy helps Clang understand Qt semantics. It prints out Qt related compiler + warnings, ranging from unnecessary memory allocation to misuse of API and + provides refactoring actions for fixing some of the issues. + \section1 Activating Clang Code Model If you build \QC yourself, ensure that the plugin is also built, as @@ -176,6 +192,9 @@ {Options to Request or Suppress Warnings} or the GCC or Clang manual pages. + \li In the \uicontrol {Clang Plugins} field, select the Clang-Tidy and + Clazy checks to perform. + \endlist You can specify Clang settings at project level in the build settings of diff --git a/doc/src/editors/creator-editors.qdoc b/doc/src/editors/creator-editors.qdoc index 72023523c3b..658a4d686e2 100644 --- a/doc/src/editors/creator-editors.qdoc +++ b/doc/src/editors/creator-editors.qdoc @@ -2851,6 +2851,9 @@ \li Locating files belonging to your project (\c {p}), such as source, header resource, and \c {.ui} files, or to any project (\c {a}) + \li Locating bookmarks (\c {b}). + For more information, see \l{Using Bookmarks}. + \li Locating class (\c {c}), enum, and function (m) definitions in your project or anywhere referenced from your project (\c {:}) @@ -2874,6 +2877,8 @@ \li Executing version control system commands (\c {git}). For more information, see \l{Using Version Control Systems} + \li Triggering menu items from the main menu (\c {t}) + \li Running external tools (\c x) \endlist @@ -2914,6 +2919,10 @@ followed by \key Space, followed by path and file name, and then press \key Enter. + You can use the filter that triggers menu commands to open sessions. Enter + \c {t yoursess} or \c {t sess yoursess} to trigger \uicontrol File > + \uicontrol Sessions > \e yoursessionname. + By default, the following filters are enabled and you do not need to use their prefixes explicitly: diff --git a/doc/src/howto/creator-sessions.qdoc b/doc/src/howto/creator-sessions.qdoc index dc73f9bceb1..bb627e607e2 100644 --- a/doc/src/howto/creator-sessions.qdoc +++ b/doc/src/howto/creator-sessions.qdoc @@ -98,6 +98,9 @@ \image qtcreator-welcome-session.png + You can also use the \c t locator filter to open a session. For more + information, see \l{Searching with the Locator}. + To view more information about a session, select the down arrow icon that appears when you move the mouse cursor over the session name. Select actions to clone, rename, and delete sessions. diff --git a/doc/src/howto/creator-ui.qdoc b/doc/src/howto/creator-ui.qdoc index 6c7a8a1d5f5..b6ccd840f54 100644 --- a/doc/src/howto/creator-ui.qdoc +++ b/doc/src/howto/creator-ui.qdoc @@ -261,7 +261,11 @@ \image qtcreator-filesystem-view.png By default, the contents of the directory that contains the file currently - active in the editor are displayed. To move to the root directory of the + active in the editor are displayed. The path to the active file is displayed + as bread crumbs. You can move to any directory along the path by clicking + it. + + To move to the root directory of the file system, select \uicontrol Computer in the menu (1). Select \uicontrol Home to move to the user's home directory. Further, you can select a project to move to an open project or \uicontrol Projects to open @@ -288,6 +292,14 @@ \li Search from the selected directory. + \li Create new files. For more information, see + \l{Adding Files to Projects}. + + \li Rename or remove existing files. + + \li Compare the selected file with the currently open file in the diff + editor. For more information, see \l{Comparing Files}. + \li Display the contents of a particular directory in the view. \endlist diff --git a/doc/src/vcs/creator-vcs-git.qdoc b/doc/src/vcs/creator-vcs-git.qdoc index 07214d77096..56d77d969f8 100644 --- a/doc/src/vcs/creator-vcs-git.qdoc +++ b/doc/src/vcs/creator-vcs-git.qdoc @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt Creator documentation. @@ -124,6 +124,9 @@ \uicontrol {Fixup Previous Commit}. This operation is done using interactive rebase. In case of conflicts, a merge tool is suggested. + To recover removed files, select \uicontrol Tools > \uicontrol Git > + \uicontrol {Recover Deleted Files}. + To change a series of commits in the local repository, select \uicontrol Tools > \uicontrol Git > \uicontrol {Local Repository} > \uicontrol {Interactive Rebase}. You can reorder or discard commits, squash diff --git a/doc/src/vcs/creator-vcs.qdoc b/doc/src/vcs/creator-vcs.qdoc index 29784b109aa..31dc3c14c61 100644 --- a/doc/src/vcs/creator-vcs.qdoc +++ b/doc/src/vcs/creator-vcs.qdoc @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt Creator documentation. @@ -234,6 +234,9 @@ show annotation views of previous versions (see \l{Annotating Files}). With Git you can also choose to cherry-pick or revert a change. + With Git, you can click \inlineimage reload_gray.png + (\uicontrol Reload) to rescan the files. + \section2 Annotating Files Annotation views are obtained by selecting \uicontrol{Annotate} or \uicontrol{Blame}. @@ -250,6 +253,9 @@ The same context menu is available when right-clicking on a version identifier in the file log view of a single file. + With Git, you can click \inlineimage reload_gray.png + (\uicontrol Reload) to rescan the files. + \section2 Committing Changes Once you have finished making changes, submit them to the version control diff --git a/qbs/modules/libclang/functions.js b/qbs/modules/libclang/functions.js index 29d093dcada..7d5e4149fca 100644 --- a/qbs/modules/libclang/functions.js +++ b/qbs/modules/libclang/functions.js @@ -16,7 +16,10 @@ function readOutput(executable, args) function readListOutput(executable, args) { - return readOutput(executable, args).split(/\s+/); + var list = readOutput(executable, args).split(/\s+/); + if (!list[list.length - 1]) + list.pop(); + return list; } function isSuitableLLVMConfig(llvmConfigCandidate, qtcFunctions) diff --git a/qbs/modules/qbsbuildconfig/qbsbuildconfig.qbs b/qbs/modules/qbsbuildconfig/qbsbuildconfig.qbs index 6c770999069..ed754e43da9 100644 --- a/qbs/modules/qbsbuildconfig/qbsbuildconfig.qbs +++ b/qbs/modules/qbsbuildconfig/qbsbuildconfig.qbs @@ -9,6 +9,7 @@ Module { property bool enableUnitTests: false property bool enableProjectFileUpdates: true property bool installApiHeaders: false + property bool enableBundledQt: false property string libInstallDir: qtc.ide_library_path property stringList libRPaths: qbs.targetOS.contains("macos") ? ["@loader_path/" + FileInfo.relativePath('/' + appInstallDir, '/' + libInstallDir)] diff --git a/qtcreator.pro b/qtcreator.pro index c8ea8ddd37d..f52b6c242c8 100644 --- a/qtcreator.pro +++ b/qtcreator.pro @@ -118,7 +118,7 @@ macx { } else { BINDIST_SOURCE = "$(INSTALL_ROOT)$$QTC_PREFIX" BINDIST_EXCLUDE_ARG = "--exclude-toplevel" - deployqt.commands = python -u $$PWD/scripts/deployqt.py -i \"$(INSTALL_ROOT)$$QTC_PREFIX\" \"$(QMAKE)\" + deployqt.commands = python -u $$PWD/scripts/deployqt.py -i \"$(INSTALL_ROOT)$$QTC_PREFIX/bin/$${IDE_APP_TARGET}\" \"$(QMAKE)\" deployqt.depends = install win32 { deployartifacts.depends = install diff --git a/scripts/deployqt.py b/scripts/deployqt.py index 75e29007552..6f6d5449f6c 100755 --- a/scripts/deployqt.py +++ b/scripts/deployqt.py @@ -43,7 +43,7 @@ debug_build = False encoding = locale.getdefaultlocale()[1] def usage(): - print("Usage: %s [qmake_path]" % os.path.basename(sys.argv[0])) + print("Usage: %s [qmake_path]" % os.path.basename(sys.argv[0])) def which(program): def is_exe(fpath): @@ -77,9 +77,6 @@ def is_debug(fpath): output = subprocess.check_output(['dumpbin', '/imports', fpath]) return coredebug.search(output.decode(encoding)) != None -def is_debug_build(install_dir): - return is_debug(os.path.join(install_dir, 'bin', 'qtcreator.exe')) - def op_failed(details = None): if details != None: print(details) @@ -274,11 +271,16 @@ def main(): ignoreErrors = True print("Note: Ignoring all errors") - if len(args) < 1: + qtcreator_binary = os.path.abspath(args[0]) + if common.is_windows_platform() and not qtcreator_binary.lower().endswith(".exe"): + qtcreator_binary = qtcreator_binary + ".exe" + + if len(args) < 1 or not os.path.isfile(qtcreator_binary): usage() sys.exit(2) - install_dir = args[0] + qtcreator_binary_path = os.path.dirname(qtcreator_binary) + install_dir = os.path.abspath(os.path.join(qtcreator_binary_path, '..')) if common.is_linux_platform(): qt_deploy_prefix = os.path.join(install_dir, 'lib', 'Qt') else: @@ -307,12 +309,14 @@ def main(): QT_INSTALL_QML = qt_install_info['QT_INSTALL_QML'] QT_INSTALL_TRANSLATIONS = qt_install_info['QT_INSTALL_TRANSLATIONS'] - plugins = ['accessible', 'codecs', 'designer', 'iconengines', 'imageformats', 'platformthemes', 'platforminputcontexts', 'platforms', 'printsupport', 'sqldrivers', 'styles', 'xcbglintegrations'] + plugins = ['accessible', 'codecs', 'designer', 'iconengines', 'imageformats', 'platformthemes', + 'platforminputcontexts', 'platforms', 'printsupport', 'sqldrivers', 'styles', + 'xcbglintegrations', 'qmltooling'] imports = ['Qt', 'QtWebKit'] if common.is_windows_platform(): global debug_build - debug_build = is_debug_build(install_dir) + debug_build = is_debug(qtcreator_binary) if common.is_windows_platform(): copy_qt_libs(qt_deploy_prefix, QT_INSTALL_BINS, QT_INSTALL_BINS, QT_INSTALL_PLUGINS, QT_INSTALL_IMPORTS, QT_INSTALL_QML, plugins, imports) diff --git a/scripts/qdoc2tasks.pl b/scripts/qdoc2tasks.pl index 066a857c272..244a0a13a4d 100755 --- a/scripts/qdoc2tasks.pl +++ b/scripts/qdoc2tasks.pl @@ -41,8 +41,9 @@ use warnings; while (my $line = ) { chomp($line); # --- extract file name based matching: - # D:/.../qaxbase.cpp:3231: warning: Cannot tie this documentation to anything - if ($line =~ /^(..[^:]*):(\d+): warning: (.*)$/) { + # Qt 5.10: D:/.../qaxbase.cpp:3231: warning: Cannot tie this documentation to anything + # Qt 5.11: D:/.../qaxbase.cpp:3231: (qdoc) warning: Cannot tie this documentation to anything + if ($line =~ /^(..[^:]*):(\d+): (?:\(qdoc\) )?warning: (.*)$/) { my $fileName = $1; my $lineNumber = $2; my $text = $3; diff --git a/share/qtcreator/qml-type-descriptions/qmlproject.qmltypes b/share/qtcreator/qml-type-descriptions/qmlproject.qmltypes index c7e7cdf937a..70003d049f9 100644 --- a/share/qtcreator/qml-type-descriptions/qmlproject.qmltypes +++ b/share/qtcreator/qml-type-descriptions/qmlproject.qmltypes @@ -11,7 +11,7 @@ Module { "QmlProject/Project 1.1" ] Property { name: "sourceDirectory"; type: "string" } - Property { name: "targetDirectory": type: "string" } + Property { name: "targetDirectory"; type: "string" } Property { name: "mainFile"; type: "string" } Property { name: "importPaths"; type: "string"; isList: true } Property { name: "content"; type: "QmlProjectItem"; isList: true } @@ -70,4 +70,4 @@ Module { ] Property { name: "filter"; type: "string" } } -} \ No newline at end of file +} diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ExtendedFunctionButton.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ExtendedFunctionButton.qml index 492cf2f6250..c0177032b77 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ExtendedFunctionButton.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ExtendedFunctionButton.qml @@ -155,6 +155,12 @@ Item { } checkable: true } + + Controls.MenuItem { + text: qsTr("Insert keyframe") + visible: hasActiveTimeline + onTriggered: insertKeyframe(backendValue.name) + } } } } diff --git a/share/qtcreator/templates/wizards/files/modeling/scratch/wizard.json b/share/qtcreator/templates/wizards/files/modeling/scratch/wizard.json index 7f3f4219561..71bad75ddff 100644 --- a/share/qtcreator/templates/wizards/files/modeling/scratch/wizard.json +++ b/share/qtcreator/templates/wizards/files/modeling/scratch/wizard.json @@ -6,6 +6,7 @@ "trDescription": "Creates a scratch model using a temporary file.", "trDisplayName": "Scratch Model", "trDisplayCategory": "Modeling", + "iconText": "qmodel", "platformIndependent": true, "enabled": "%{JS: [ %{Plugins} ].indexOf('ModelEditor') >= 0}", diff --git a/share/qtcreator/templates/wizards/projects/qtquickapplication/CMakeLists.txt b/share/qtcreator/templates/wizards/projects/qtquickapplication/CMakeLists.txt index 1e36df0c284..07c1f586086 100644 --- a/share/qtcreator/templates/wizards/projects/qtquickapplication/CMakeLists.txt +++ b/share/qtcreator/templates/wizards/projects/qtquickapplication/CMakeLists.txt @@ -1,10 +1,12 @@ -cmake_minimum_required(VERSION 2.8.12) +cmake_minimum_required(VERSION 3.1) project(%{ProjectName} LANGUAGES CXX) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) +set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD_REQUIRED ON) find_package(Qt5 COMPONENTS Core Quick REQUIRED) diff --git a/share/qtcreator/translations/qtcreator_cs.ts b/share/qtcreator/translations/qtcreator_cs.ts index 0ef506e5575..0b0ad9d1447 100644 --- a/share/qtcreator/translations/qtcreator_cs.ts +++ b/share/qtcreator/translations/qtcreator_cs.ts @@ -57589,7 +57589,7 @@ Má se to zkusit ještě jednou? - QmlProfiler::Internal::QmlProfilerEventsMainView + QmlProfiler::Internal::QmlProfilerStatisticsMainView Location Umístění diff --git a/share/qtcreator/translations/qtcreator_fr.ts b/share/qtcreator/translations/qtcreator_fr.ts index 3469e6780ed..16d3b304730 100644 --- a/share/qtcreator/translations/qtcreator_fr.ts +++ b/share/qtcreator/translations/qtcreator_fr.ts @@ -58942,7 +58942,7 @@ Voulez-vous la tuer ? - QmlProfiler::Internal::QmlProfilerEventsMainView + QmlProfiler::Internal::QmlProfilerStatisticsMainView Location Emplacement diff --git a/share/qtcreator/translations/qtcreator_uk.ts b/share/qtcreator/translations/qtcreator_uk.ts index 33c48c0773e..8a20f959d43 100644 --- a/share/qtcreator/translations/qtcreator_uk.ts +++ b/share/qtcreator/translations/qtcreator_uk.ts @@ -30492,7 +30492,7 @@ Do you want to kill it? - QmlProfiler::Internal::QmlProfilerEventsMainView + QmlProfiler::Internal::QmlProfilerStatisticsMainView Location Розташування diff --git a/share/qtcreator/translations/qtcreator_zh_CN.ts b/share/qtcreator/translations/qtcreator_zh_CN.ts index 1cc26a1ef98..74d7dac92c2 100644 --- a/share/qtcreator/translations/qtcreator_zh_CN.ts +++ b/share/qtcreator/translations/qtcreator_zh_CN.ts @@ -55655,7 +55655,7 @@ Do you want to retry? - QmlProfiler::Internal::QmlProfilerEventsMainView + QmlProfiler::Internal::QmlProfilerStatisticsMainView Location 路径 diff --git a/share/qtcreator/translations/qtcreator_zh_TW.ts b/share/qtcreator/translations/qtcreator_zh_TW.ts index bc117ee0ce2..4e1339a0cde 100644 --- a/share/qtcreator/translations/qtcreator_zh_TW.ts +++ b/share/qtcreator/translations/qtcreator_zh_TW.ts @@ -32076,7 +32076,7 @@ Do you want to kill it? - QmlProfiler::Internal::QmlProfilerEventsMainView + QmlProfiler::Internal::QmlProfilerStatisticsMainView Location 位置 diff --git a/src/libs/flamegraph/qml/FlameGraphDetails.qml b/src/libs/flamegraph/qml/FlameGraphDetails.qml index e3f2fde97f4..2f1110090ab 100644 --- a/src/libs/flamegraph/qml/FlameGraphDetails.qml +++ b/src/libs/flamegraph/qml/FlameGraphDetails.qml @@ -153,9 +153,10 @@ Item { spacing: innerMargin columns: 2 property int minimumWidth: { + // max(width of longest label * 2, minimumInnerWidth) var result = minimumInnerWidth; - for (var i = 0; i < children.length; ++i) - result = Math.max(children[i].x, result); + for (var i = 0; i < children.length; i += 2) + result = Math.max(children[i].implicitWidth * 2 + innerMargin, result); return result + 2 * outerMargin; } @@ -170,8 +171,8 @@ Item { property bool isLabel: index % 2 === 0 font.bold: isLabel elide: Text.ElideRight - width: text === "" ? 0 : (isLabel ? implicitWidth : - (dragHandle.x - x - innerMargin)) + width: (text === "" || isLabel) + ? implicitWidth : (dragHandle.x - col.minimumWidth / 2 - innerMargin) text: isLabel ? (modelData + ":") : modelData color: contentTextColor } diff --git a/src/libs/timeline/qml/RangeDetails.qml b/src/libs/timeline/qml/RangeDetails.qml index 6b42bbc934f..9b9ff77d7fe 100644 --- a/src/libs/timeline/qml/RangeDetails.qml +++ b/src/libs/timeline/qml/RangeDetails.qml @@ -176,9 +176,10 @@ Item { spacing: 5 columns: 2 property int minimumWidth: { + // max(width of longest label * 2, 150) var result = 150; - for (var i = 0; i < children.length; ++i) - result = Math.max(children[i].x, result); + for (var i = 0; i < children.length; i += 2) + result = Math.max(children[i].implicitWidth * 2 + spacing, result); return result + 20; } @@ -190,7 +191,7 @@ Item { Repeater { model: eventInfo Detail { - valueWidth: dragHandle.x - x - 15 + valueWidth: (dragHandle.x - col.minimumWidth / 2 - col.spacing) isLabel: index % 2 === 0 text: (content === undefined) ? "" : (isLabel ? (content + ":") : content) } diff --git a/src/libs/utils/environment.cpp b/src/libs/utils/environment.cpp index 0705c300818..74534eeaf4b 100644 --- a/src/libs/utils/environment.cpp +++ b/src/libs/utils/environment.cpp @@ -500,7 +500,7 @@ Environment::const_iterator Environment::constEnd() const Environment::const_iterator Environment::constFind(const QString &name) const { - return m_values.constFind(name); + return findKey(m_values, m_osType, name); } int Environment::size() const @@ -567,6 +567,11 @@ bool Environment::hasKey(const QString &key) const return m_values.contains(key); } +OsType Environment::osType() const +{ + return m_osType; +} + QString Environment::userName() const { return value(QString::fromLatin1(m_osType == OsTypeWindows ? "USERNAME" : "USER")); diff --git a/src/libs/utils/environment.h b/src/libs/utils/environment.h index e3a382daf04..4fed80a8bb3 100644 --- a/src/libs/utils/environment.h +++ b/src/libs/utils/environment.h @@ -91,6 +91,7 @@ public: /// Return the Environment changes necessary to modify this into the other environment. QList diff(const Environment &other, bool checkAppendPrepend = false) const; bool hasKey(const QString &key) const; + OsType osType() const; QString userName() const; diff --git a/src/libs/utils/environmentmodel.cpp b/src/libs/utils/environmentmodel.cpp index 4191d3abeee..fde8e7ad550 100644 --- a/src/libs/utils/environmentmodel.cpp +++ b/src/libs/utils/environmentmodel.cpp @@ -364,6 +364,13 @@ void EnvironmentModel::setUserChanges(QList list) name = name.trimmed(); if (name.startsWith(QLatin1String("export "))) name = name.mid(7).trimmed(); + if (d->m_baseEnvironment.osType() == OsTypeWindows) { + // Environment variable names are case-insensitive under windows, but we still + // want to preserve the case of pre-existing variables. + auto it = d->m_baseEnvironment.constFind(name); + if (it != d->m_baseEnvironment.constEnd()) + name = d->m_baseEnvironment.key(it); + } } d->updateResultEnvironment(); diff --git a/src/plugins/autotest/gtest/gtesttreeitem.cpp b/src/plugins/autotest/gtest/gtesttreeitem.cpp index e31bd5ec3fb..4e1f7737024 100644 --- a/src/plugins/autotest/gtest/gtesttreeitem.cpp +++ b/src/plugins/autotest/gtest/gtesttreeitem.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include namespace Autotest { @@ -122,35 +123,67 @@ TestConfiguration *GTestTreeItem::debugConfiguration() const return config; } -QList GTestTreeItem::getAllTestConfigurations() const +struct TestCases +{ + QStringList filters; + int testSetCount = 0; + QSet internalTargets; +}; + +static void collectTestInfo(const GTestTreeItem *item, + QHash &testCasesForProFile, + bool ignoreCheckState) +{ + QTC_ASSERT(item, return); + if (item->type() == TestTreeItem::GroupNode) { + for (int row = 0, count = item->childCount(); row < count; ++row) { + auto child = static_cast(item->childItem(row)); + collectTestInfo(child, testCasesForProFile, ignoreCheckState); + } + return; + } + const int childCount = item->childCount(); + QTC_ASSERT(childCount != 0, return); + QTC_ASSERT(item->type() == TestTreeItem::TestCase, return); + if (ignoreCheckState || item->checked() == Qt::Checked) { + const QString &projectFile = item->childItem(0)->proFile(); + testCasesForProFile[projectFile].filters.append( + gtestFilter(item->state()).arg(item->name()).arg('*')); + testCasesForProFile[projectFile].testSetCount += childCount - 1; + testCasesForProFile[projectFile].internalTargets.unite(item->internalTargets()); + } else if (item->checked() == Qt::PartiallyChecked) { + for (int childRow = 0; childRow < childCount; ++childRow) { + const TestTreeItem *child = item->childItem(childRow); + QTC_ASSERT(child->type() == TestTreeItem::TestFunctionOrSet, continue); + if (child->checked() == Qt::Checked) { + testCasesForProFile[child->proFile()].filters.append( + gtestFilter(item->state()).arg(item->name()).arg(child->name())); + testCasesForProFile[child->proFile()].internalTargets.unite( + child->internalTargets()); + } + } + } +} + +QList GTestTreeItem::getTestConfigurations(bool ignoreCheckState) const { QList result; - ProjectExplorer::Project *project = ProjectExplorer::SessionManager::startupProject(); if (!project || type() != Root) return result; - QHash proFilesWithTestSets; - QHash > proFilesWithInternalTargets; + QHash testCasesForProFile; for (int row = 0, count = childCount(); row < count; ++row) { - const GTestTreeItem *child = static_cast(childItem(row)); - - const int grandChildCount = child->childCount(); - for (int grandChildRow = 0; grandChildRow < grandChildCount; ++grandChildRow) { - const TestTreeItem *grandChild = child->childItem(grandChildRow); - const QString &key = grandChild->proFile(); - proFilesWithTestSets.insert(key, proFilesWithTestSets[key] + 1); - proFilesWithInternalTargets[key].unite(grandChild->internalTargets()); - } + auto child = static_cast(childItem(row)); + collectTestInfo(child, testCasesForProFile, ignoreCheckState); } - QHash::ConstIterator it = proFilesWithTestSets.begin(); - QHash::ConstIterator end = proFilesWithTestSets.end(); - for ( ; it != end; ++it) { - const QSet &internalTargets = proFilesWithInternalTargets[it.key()]; - for (const QString &target : internalTargets) { + for (auto it = testCasesForProFile.begin(), end = testCasesForProFile.end(); it != end; ++it) { + for (const QString &target : Utils::asConst(it.value().internalTargets)) { GTestConfiguration *tc = new GTestConfiguration; - tc->setTestCaseCount(it.value()); + if (!ignoreCheckState) + tc->setTestCases(it.value().filters); + tc->setTestCaseCount(tc->testCaseCount() + it.value().testSetCount); tc->setProjectFile(it.key()); tc->setProject(project); tc->setInternalTarget(target); @@ -161,69 +194,14 @@ QList GTestTreeItem::getAllTestConfigurations() const return result; } -struct TestCases +QList GTestTreeItem::getAllTestConfigurations() const { - QStringList filters; - int additionalTestCaseCount = 0; -}; + return getTestConfigurations(true); +} QList GTestTreeItem::getSelectedTestConfigurations() const { - QList result; - ProjectExplorer::Project *project = ProjectExplorer::SessionManager::startupProject(); - if (!project || type() != Root) - return result; - - QHash proFilesWithCheckedTestSets; - QHash > proFilesWithInternalTargets; - for (int row = 0, count = childCount(); row < count; ++row) { - const GTestTreeItem *child = static_cast(childItem(row)); - - const int grandChildCount = child->childCount(); - QTC_ASSERT(grandChildCount != 0, continue); - - switch (child->checked()) { - case Qt::Unchecked: - continue; - case Qt::Checked: { - auto &testCases = proFilesWithCheckedTestSets[child->childItem(0)->proFile()]; - testCases.filters.append(gtestFilter(child->state()).arg(child->name()).arg('*')); - testCases.additionalTestCaseCount += grandChildCount - 1; - proFilesWithInternalTargets[child->childItem(0)->proFile()].unite( - child->internalTargets()); - break; - } - case Qt::PartiallyChecked: { - for (int grandChildRow = 0; grandChildRow < grandChildCount; ++grandChildRow) { - const TestTreeItem *grandChild = child->childItem(grandChildRow); - if (grandChild->checked() == Qt::Checked) { - proFilesWithCheckedTestSets[grandChild->proFile()].filters.append( - gtestFilter(child->state()).arg(child->name()).arg(grandChild->name())); - proFilesWithInternalTargets[grandChild->proFile()].unite( - grandChild->internalTargets()); - } - } - break; - } - } - } - - QHash::ConstIterator it = proFilesWithCheckedTestSets.begin(); - QHash::ConstIterator end = proFilesWithCheckedTestSets.end(); - for ( ; it != end; ++it) { - const QSet &internalTargets = proFilesWithInternalTargets[it.key()]; - for (const QString &target : internalTargets) { - GTestConfiguration *tc = new GTestConfiguration; - tc->setTestCases(it.value().filters); - tc->setTestCaseCount(tc->testCaseCount() + it.value().additionalTestCaseCount); - tc->setProjectFile(it.key()); - tc->setProject(project); - tc->setInternalTarget(target); - result << tc; - } - } - - return result; + return getTestConfigurations(false); } TestTreeItem *GTestTreeItem::find(const TestParseResult *result) diff --git a/src/plugins/autotest/gtest/gtesttreeitem.h b/src/plugins/autotest/gtest/gtesttreeitem.h index 7aad3563dd8..81a89e45ec8 100644 --- a/src/plugins/autotest/gtest/gtesttreeitem.h +++ b/src/plugins/autotest/gtest/gtesttreeitem.h @@ -71,6 +71,7 @@ public: private: bool modifyTestSetContent(const GTestParseResult *result); + QList getTestConfigurations(bool ignoreCheckState) const; GTestTreeItem::TestStates m_state; }; diff --git a/src/plugins/autotest/qtest/qttesttreeitem.cpp b/src/plugins/autotest/qtest/qttesttreeitem.cpp index a06598db74e..1502a0954bc 100644 --- a/src/plugins/autotest/qtest/qttesttreeitem.cpp +++ b/src/plugins/autotest/qtest/qttesttreeitem.cpp @@ -38,7 +38,7 @@ QtTestTreeItem::QtTestTreeItem(const QString &name, const QString &filePath, Tes : TestTreeItem(name, filePath, type) { if (type == TestDataTag) - setChecked(Qt::Checked); + setData(0, Qt::Checked, Qt::CheckStateRole); } QVariant QtTestTreeItem::data(int column, int role) const @@ -139,6 +139,53 @@ TestConfiguration *QtTestTreeItem::testConfiguration() const return config; } +static void fillTestConfigurationsFromCheckState(const TestTreeItem *item, + QList &testConfigurations) +{ + QTC_ASSERT(item, return); + if (item->type() == TestTreeItem::GroupNode) { + for (int row = 0, count = item->childCount(); row < count; ++row) + fillTestConfigurationsFromCheckState(item->childItem(row), testConfigurations); + return; + } + QTC_ASSERT(item->type() == TestTreeItem::TestCase, return); + QtTestConfiguration *testConfig = nullptr; + switch (item->checked()) { + case Qt::Unchecked: + return; + case Qt::Checked: + testConfig = static_cast(item->testConfiguration()); + QTC_ASSERT(testConfig, return); + testConfigurations << testConfig; + return; + case Qt::PartiallyChecked: + default: + int grandChildCount = item->childCount(); + QStringList testCases; + for (int grandChildRow = 0; grandChildRow < grandChildCount; ++grandChildRow) { + const TestTreeItem *grandChild = item->childItem(grandChildRow); + if (grandChild->checked() == Qt::Checked) { + testCases << grandChild->name(); + } else if (grandChild->checked() == Qt::PartiallyChecked) { + const int dtCount = grandChild->childCount(); + const QString funcName = grandChild->name(); + for (int dtRow = 0; dtRow < dtCount; ++dtRow) { + const TestTreeItem *dataTag = grandChild->childItem(dtRow); + if (dataTag->checked() == Qt::Checked) + testCases << funcName + ':' + dataTag->name(); + } + } + } + + testConfig = new QtTestConfiguration(); + testConfig->setTestCases(testCases); + testConfig->setProjectFile(item->proFile()); + testConfig->setProject(ProjectExplorer::SessionManager::startupProject()); + testConfig->setInternalTargets(item->internalTargets()); + testConfigurations << testConfig; + } +} + TestConfiguration *QtTestTreeItem::debugConfiguration() const { QtTestConfiguration *config = static_cast(testConfiguration()); @@ -157,13 +204,19 @@ QList QtTestTreeItem::getAllTestConfigurations() const for (int row = 0, count = childCount(); row < count; ++row) { const TestTreeItem *child = childItem(row); - - TestConfiguration *tc = new QtTestConfiguration(); - tc->setTestCaseCount(child->childCount()); - tc->setProjectFile(child->proFile()); - tc->setProject(project); - tc->setInternalTargets(child->internalTargets()); - result << tc; + TestConfiguration *tc = nullptr; + if (child->type() == TestCase) { + tc = child->testConfiguration(); + QTC_ASSERT(tc, continue); + result << tc; + } else if (child->type() == GroupNode) { + const int groupChildCount = child->childCount(); + for (int groupChildRow = 0; groupChildRow < groupChildCount; ++groupChildRow) { + tc = child->childItem(groupChildRow)->testConfiguration(); + QTC_ASSERT(tc, continue); + result << tc; + } + } } return result; } @@ -175,49 +228,8 @@ QList QtTestTreeItem::getSelectedTestConfigurations() const if (!project || type() != Root) return result; - QtTestConfiguration *testConfiguration = nullptr; - - for (int row = 0, count = childCount(); row < count; ++row) { - const TestTreeItem *child = childItem(row); - - switch (child->checked()) { - case Qt::Unchecked: - continue; - case Qt::Checked: - testConfiguration = new QtTestConfiguration(); - testConfiguration->setTestCaseCount(child->childCount()); - testConfiguration->setProjectFile(child->proFile()); - testConfiguration->setProject(project); - testConfiguration->setInternalTargets(child->internalTargets()); - result << testConfiguration; - continue; - case Qt::PartiallyChecked: - default: - int grandChildCount = child->childCount(); - QStringList testCases; - for (int grandChildRow = 0; grandChildRow < grandChildCount; ++grandChildRow) { - const TestTreeItem *grandChild = child->childItem(grandChildRow); - if (grandChild->checked() == Qt::Checked) { - testCases << grandChild->name(); - } else if (grandChild->checked() == Qt::PartiallyChecked) { - const int dtCount = grandChild->childCount(); - const QString funcName = grandChild->name(); - for (int dtRow = 0; dtRow < dtCount; ++dtRow) { - const TestTreeItem *dataTag = grandChild->childItem(dtRow); - if (dataTag->checked() == Qt::Checked) - testCases << funcName + ':' + dataTag->name(); - } - } - } - - testConfiguration = new QtTestConfiguration(); - testConfiguration->setTestCases(testCases); - testConfiguration->setProjectFile(child->proFile()); - testConfiguration->setProject(project); - testConfiguration->setInternalTargets(child->internalTargets()); - result << testConfiguration; - } - } + for (int row = 0, count = childCount(); row < count; ++row) + fillTestConfigurationsFromCheckState(childItem(row), result); return result; } diff --git a/src/plugins/autotest/quick/quicktesttreeitem.cpp b/src/plugins/autotest/quick/quicktesttreeitem.cpp index 098e7c37689..6d3a2b99f48 100644 --- a/src/plugins/autotest/quick/quicktesttreeitem.cpp +++ b/src/plugins/autotest/quick/quicktesttreeitem.cpp @@ -153,6 +153,43 @@ TestConfiguration *QuickTestTreeItem::testConfiguration() const return config; } +static void testConfigurationFromCheckState(const TestTreeItem *item, + QHash &foundProFiles) +{ + QTC_ASSERT(item, return); + if (item->type() == TestTreeItem::GroupNode) { + for (int row = 0, count = item->childCount(); row < count; ++row) + testConfigurationFromCheckState(item->childItem(row), foundProFiles); + return; + } + QTC_ASSERT(item->type() == TestTreeItem::TestCase, return); + QuickTestConfiguration *tc = nullptr; + if (item->checked() == Qt::Unchecked) + return; + + QStringList testFunctions; + const int childCount = item->childCount(); + for (int childRow = 0; childRow < childCount; ++childRow) { + const TestTreeItem *child = item->childItem(childRow); + if (child->checked() != Qt::Checked || child->type() != TestTreeItem::TestFunctionOrSet) + continue; + testFunctions << item->name() + "::" + child->name(); + } + if (foundProFiles.contains(item->proFile())) { + tc = foundProFiles[item->proFile()]; + QStringList oldFunctions(tc->testCases()); + oldFunctions << testFunctions; + tc->setTestCases(oldFunctions); + } else { + tc = new QuickTestConfiguration; + tc->setTestCases(testFunctions); + tc->setProjectFile(item->proFile()); + tc->setProject(ProjectExplorer::SessionManager::startupProject()); + tc->setInternalTargets(item->internalTargets()); + foundProFiles.insert(item->proFile(), tc); + } +} + TestConfiguration *QuickTestTreeItem::debugConfiguration() const { QuickTestConfiguration *config = static_cast(testConfiguration()); @@ -161,6 +198,17 @@ TestConfiguration *QuickTestTreeItem::debugConfiguration() const return config; } +struct Tests { + int testCount = 0; + QSet internalTargets; +}; + +static void addTestsForItem(Tests &tests, const TestTreeItem *item) +{ + tests.testCount += item->childCount(); + tests.internalTargets = item->internalTargets(); +} + QList QuickTestTreeItem::getAllTestConfigurations() const { QList result; @@ -169,8 +217,7 @@ QList QuickTestTreeItem::getAllTestConfigurations() const if (!project || type() != Root) return result; - QHash foundProFiles; - QHash > proFilesWithTargets; + QHash testsForProfile; for (int row = 0, count = childCount(); row < count; ++row) { const TestTreeItem *child = childItem(row); // unnamed Quick Tests must be handled separately @@ -178,25 +225,29 @@ QList QuickTestTreeItem::getAllTestConfigurations() const for (int childRow = 0, ccount = child->childCount(); childRow < ccount; ++ childRow) { const TestTreeItem *grandChild = child->childItem(childRow); const QString &proFile = grandChild->proFile(); - foundProFiles.insert(proFile, foundProFiles[proFile] + 1); - proFilesWithTargets.insert(proFile, grandChild->internalTargets()); + ++(testsForProfile[proFile].testCount); + testsForProfile[proFile].internalTargets = grandChild->internalTargets(); } continue; } // named Quick Test - const QString &proFile = child->proFile(); - foundProFiles.insert(proFile, foundProFiles[proFile] + child->childCount()); - proFilesWithTargets.insert(proFile, child->internalTargets()); + if (child->type() == TestCase) { + addTestsForItem(testsForProfile[child->proFile()], child); + } else if (child->type() == GroupNode) { + const int groupCount = child->childCount(); + for (int groupRow = 0; groupRow < groupCount; ++groupRow) { + const TestTreeItem *grandChild = child->childItem(groupRow); + addTestsForItem(testsForProfile[grandChild->proFile()], grandChild); + } + } } // create TestConfiguration for each project file - QHash::ConstIterator it = foundProFiles.begin(); - QHash::ConstIterator end = foundProFiles.end(); - for ( ; it != end; ++it) { + for (auto it = testsForProfile.begin(), end = testsForProfile.end(); it != end; ++it) { QuickTestConfiguration *tc = new QuickTestConfiguration; - tc->setTestCaseCount(it.value()); + tc->setTestCaseCount(it.value().testCount); tc->setProjectFile(it.key()); tc->setProject(project); - tc->setInternalTargets(proFilesWithTargets[it.key()]); + tc->setInternalTargets(it.value().internalTargets); result << tc; } return result; @@ -209,7 +260,6 @@ QList QuickTestTreeItem::getSelectedTestConfigurations() co if (!project || type() != Root) return result; - QuickTestConfiguration *tc = nullptr; QHash foundProFiles; for (int row = 0, count = childCount(); row < count; ++row) { @@ -219,39 +269,10 @@ QList QuickTestTreeItem::getSelectedTestConfigurations() co continue; // named Quick Tests - switch (child->checked()) { - case Qt::Unchecked: - continue; - case Qt::Checked: - case Qt::PartiallyChecked: - default: - QStringList testFunctions; - int grandChildCount = child->childCount(); - for (int grandChildRow = 0; grandChildRow < grandChildCount; ++grandChildRow) { - const TestTreeItem *grandChild = child->childItem(grandChildRow); - if (grandChild->checked() != Qt::Checked || grandChild->type() != TestFunctionOrSet) - continue; - testFunctions << child->name() + "::" + grandChild->name(); - } - if (foundProFiles.contains(child->proFile())) { - tc = foundProFiles[child->proFile()]; - QStringList oldFunctions(tc->testCases()); - oldFunctions << testFunctions; - tc->setTestCases(oldFunctions); - } else { - tc = new QuickTestConfiguration; - tc->setTestCases(testFunctions); - tc->setProjectFile(child->proFile()); - tc->setProject(project); - tc->setInternalTargets(child->internalTargets()); - foundProFiles.insert(child->proFile(), tc); - } - break; - } + testConfigurationFromCheckState(child, foundProFiles); } - QHash::ConstIterator it = foundProFiles.begin(); - QHash::ConstIterator end = foundProFiles.end(); - for ( ; it != end; ++it) { + + for (auto it = foundProFiles.begin(), end = foundProFiles.end(); it != end; ++it) { QuickTestConfiguration *config = it.value(); if (!config->unnamedOnly()) result << config; @@ -327,6 +348,12 @@ bool QuickTestTreeItem::isGroupNodeFor(const TestTreeItem *other) const return TestTreeItem::isGroupNodeFor(other); } +bool QuickTestTreeItem::removeOnSweepIfEmpty() const +{ + return TestTreeItem::removeOnSweepIfEmpty() + || (type() == TestCase && name().isEmpty()); // remove pseudo item '' +} + TestTreeItem *QuickTestTreeItem::createParentGroupNode() const { if (filePath().isEmpty() || name().isEmpty()) diff --git a/src/plugins/autotest/quick/quicktesttreeitem.h b/src/plugins/autotest/quick/quicktesttreeitem.h index b7116125e30..30b5efd317b 100644 --- a/src/plugins/autotest/quick/quicktesttreeitem.h +++ b/src/plugins/autotest/quick/quicktesttreeitem.h @@ -48,6 +48,7 @@ public: bool modify(const TestParseResult *result) override; bool lessThan(const TestTreeItem *other, SortMode mode) const override; bool isGroupNodeFor(const TestTreeItem *other) const override; + bool removeOnSweepIfEmpty() const override; TestTreeItem *createParentGroupNode() const override; QSet internalTargets() const override; private: diff --git a/src/plugins/autotest/testresultdelegate.cpp b/src/plugins/autotest/testresultdelegate.cpp index 076adbc3aa1..a8e0b4fbe82 100644 --- a/src/plugins/autotest/testresultdelegate.cpp +++ b/src/plugins/autotest/testresultdelegate.cpp @@ -55,13 +55,11 @@ void TestResultDelegate::paint(QPainter *painter, const QStyleOptionViewItem &op { QStyleOptionViewItem opt = option; initStyleOption(&opt, index); - painter->save(); QFontMetrics fm(opt.font); QBrush background; QColor foreground; - const QAbstractItemView *view = qobject_cast(opt.widget); const bool selected = opt.state & QStyle::State_Selected; if (selected) { @@ -71,10 +69,14 @@ void TestResultDelegate::paint(QPainter *painter, const QStyleOptionViewItem &op background = opt.palette.window().color(); foreground = opt.palette.text().color(); } + + auto resultFilterModel = qobject_cast(index.model()); + if (!resultFilterModel) + return; + painter->save(); painter->fillRect(opt.rect, background); painter->setPen(foreground); - TestResultFilterModel *resultFilterModel = static_cast(view->model()); LayoutPositions positions(opt, resultFilterModel); const TestResult *testResult = resultFilterModel->testResult(index); QTC_ASSERT(testResult, painter->restore();return); diff --git a/src/plugins/autotest/testresultdelegate.h b/src/plugins/autotest/testresultdelegate.h index 2161906a606..bc61f2a0675 100644 --- a/src/plugins/autotest/testresultdelegate.h +++ b/src/plugins/autotest/testresultdelegate.h @@ -56,7 +56,7 @@ private: class LayoutPositions { public: - LayoutPositions(QStyleOptionViewItem &options, TestResultFilterModel *filterModel) + LayoutPositions(QStyleOptionViewItem &options, const TestResultFilterModel *filterModel) : m_totalWidth(options.rect.width()), m_top(options.rect.top()), m_bottom(options.rect.bottom()) diff --git a/src/plugins/autotest/testtreeitem.cpp b/src/plugins/autotest/testtreeitem.cpp index 5c3b03724db..a597a2de7ad 100644 --- a/src/plugins/autotest/testtreeitem.cpp +++ b/src/plugins/autotest/testtreeitem.cpp @@ -106,9 +106,9 @@ QVariant TestTreeItem::data(int /*column*/, int role) const bool TestTreeItem::setData(int /*column*/, const QVariant &data, int role) { if (role == Qt::CheckStateRole) { - Qt::CheckState old = checked(); - setChecked((Qt::CheckState)data.toInt()); - return checked() != old; + Qt::CheckState old = m_checked; + m_checked = (Qt::CheckState)data.toInt(); + return m_checked != old; } return false; } @@ -168,34 +168,6 @@ bool TestTreeItem::modifyLineAndColumn(const TestParseResult *result) return hasBeenModified; } -void TestTreeItem::setChecked(const Qt::CheckState checkState) -{ - switch (m_type) { - case TestDataTag: { - m_checked = (checkState == Qt::Unchecked ? Qt::Unchecked : Qt::Checked); - if (auto parent = parentItem()) - parent->revalidateCheckState(); - break; - } - case Root: - case GroupNode: - case TestFunctionOrSet: - case TestCase: { - Qt::CheckState usedState = (checkState == Qt::Unchecked ? Qt::Unchecked : Qt::Checked); - for (int row = 0, count = childCount(); row < count; ++row) - childItem(row)->setChecked(usedState); - m_checked = usedState; - if (m_type != Root) { - if (auto parent = parentItem()) - parent->revalidateCheckState(); - } - break; - } - default: - return; - } -} - Qt::CheckState TestTreeItem::checked() const { switch (m_type) { @@ -327,41 +299,6 @@ QSet TestTreeItem::internalTargets() const return targets; } -void TestTreeItem::revalidateCheckState() -{ - const Type ttiType = type(); - if (ttiType != TestCase && ttiType != TestFunctionOrSet && ttiType != Root && ttiType != GroupNode) - return; - if (childCount() == 0) // can this happen? (we're calling revalidateCS() on parentItem() - return; - bool foundChecked = false; - bool foundUnchecked = false; - bool foundPartiallyChecked = false; - for (int row = 0, count = childCount(); row < count; ++row) { - TestTreeItem *child = childItem(row); - switch (child->type()) { - case TestDataFunction: - case TestSpecialFunction: - continue; - default: - break; - } - - foundChecked |= (child->checked() == Qt::Checked); - foundUnchecked |= (child->checked() == Qt::Unchecked); - foundPartiallyChecked |= (child->checked() == Qt::PartiallyChecked); - if (foundPartiallyChecked || (foundChecked && foundUnchecked)) { - m_checked = Qt::PartiallyChecked; - if (ttiType == TestFunctionOrSet || ttiType == TestCase || ttiType == GroupNode) - parentItem()->revalidateCheckState(); - return; - } - } - m_checked = (foundUnchecked ? Qt::Unchecked : Qt::Checked); - if (ttiType == TestFunctionOrSet || ttiType == TestCase || ttiType == GroupNode) - parentItem()->revalidateCheckState(); -} - inline bool TestTreeItem::modifyFilePath(const QString &filePath) { if (m_filePath != filePath) { diff --git a/src/plugins/autotest/testtreeitem.h b/src/plugins/autotest/testtreeitem.h index 33d7117e4fe..012104f91f9 100644 --- a/src/plugins/autotest/testtreeitem.h +++ b/src/plugins/autotest/testtreeitem.h @@ -89,12 +89,12 @@ public: unsigned column() const { return m_column; } QString proFile() const { return m_proFile; } void setProFile(const QString &proFile) { m_proFile = proFile; } - virtual void setChecked(const Qt::CheckState checked); virtual Qt::CheckState checked() const; Type type() const { return m_type; } void markForRemoval(bool mark); void markForRemovalRecursively(bool mark); virtual void markForRemovalRecursively(const QString &filePath); + virtual bool removeOnSweepIfEmpty() const { return m_type == GroupNode; } bool markedForRemoval() const { return m_status == MarkedForRemoval; } bool newlyAdded() const { return m_status == NewlyAdded; } TestTreeItem *parentItem() const; @@ -123,7 +123,6 @@ protected: const QString &file); private: - void revalidateCheckState(); bool modifyFilePath(const QString &filePath); bool modifyName(const QString &name); @@ -143,7 +142,7 @@ private: QString m_proFile; Status m_status = NewlyAdded; - friend class TestTreeModel; // grant access to (private) revalidateCheckState() + friend class TestTreeModel; // grant access to (protected) findChildBy() }; class TestCodeLocationAndType diff --git a/src/plugins/autotest/testtreemodel.cpp b/src/plugins/autotest/testtreemodel.cpp index 63d83e54e6a..f189c6472d6 100644 --- a/src/plugins/autotest/testtreemodel.cpp +++ b/src/plugins/autotest/testtreemodel.cpp @@ -108,21 +108,18 @@ bool TestTreeModel::setData(const QModelIndex &index, const QVariant &value, int if (item && item->setData(index.column(), value, role)) { emit dataChanged(index, index); if (role == Qt::CheckStateRole) { - switch (item->type()) { - case TestTreeItem::Root: - case TestTreeItem::GroupNode: - case TestTreeItem::TestCase: - if (item->childCount() > 0) - emit dataChanged(index.child(0, 0), index.child(item->childCount() - 1, 0)); - break; - case TestTreeItem::TestFunctionOrSet: - emit dataChanged(index.parent(), index.parent()); - break; - default: // avoid warning regarding unhandled enum member - break; + Qt::CheckState checked = item->checked(); + if (item->hasChildren() && checked != Qt::PartiallyChecked) { + // handle the new checkstate for children as well... + for (Utils::TreeItem *child : *item) { + const QModelIndex &idx = indexForItem(child); + setData(idx, checked ? Qt::Checked : Qt::Unchecked, Qt::CheckStateRole); + } } + if (item->parent() != rootItem() && item->parentItem()->checked() != checked) + revalidateCheckState(item->parentItem()); // handle parent too + return true; } - return true; } return false; } @@ -254,10 +251,14 @@ bool TestTreeModel::sweepChildren(TestTreeItem *item) if (child->type() != TestTreeItem::Root && child->markedForRemoval()) { destroyItem(child); - item->revalidateCheckState(); + revalidateCheckState(item); hasChanged = true; } else if (child->hasChildren()) { hasChanged |= sweepChildren(child); + if (!child->hasChildren() && child->removeOnSweepIfEmpty()) { + destroyItem(child); + revalidateCheckState(item); + } } else { hasChanged |= child->newlyAdded(); } @@ -281,6 +282,50 @@ void TestTreeModel::insertItemInParent(TestTreeItem *item, TestTreeItem *root, b } } parentNode->appendChild(item); + if (item->checked() != parentNode->checked()) + revalidateCheckState(parentNode); +} + +void TestTreeModel::revalidateCheckState(TestTreeItem *item) +{ + QTC_ASSERT(item, return); + + const TestTreeItem::Type type = item->type(); + if (type == TestTreeItem::TestSpecialFunction || type == TestTreeItem::TestDataFunction + || type == TestTreeItem::TestDataTag) { + return; + } + const Qt::CheckState oldState = (Qt::CheckState)item->data(0, Qt::CheckStateRole).toInt(); + Qt::CheckState newState = Qt::Checked; + bool foundChecked = false; + bool foundUnchecked = false; + bool foundPartiallyChecked = false; + for (int row = 0, count = item->childCount(); row < count; ++row) { + TestTreeItem *child = item->childItem(row); + switch (child->type()) { + case TestTreeItem::TestDataFunction: + case TestTreeItem::TestSpecialFunction: + continue; + default: + break; + } + + foundChecked |= (child->checked() == Qt::Checked); + foundUnchecked |= (child->checked() == Qt::Unchecked); + foundPartiallyChecked |= (child->checked() == Qt::PartiallyChecked); + if (foundPartiallyChecked || (foundChecked && foundUnchecked)) { + newState = Qt::PartiallyChecked; + break; + } + } + if (newState != Qt::PartiallyChecked) + newState = foundUnchecked ? Qt::Unchecked : Qt::Checked; + if (oldState != newState) { + item->setData(0, newState, Qt::CheckStateRole); + emit dataChanged(item->index(), item->index()); + if (item->parent() != rootItem() && item->parentItem()->checked() != newState) + revalidateCheckState(item->parentItem()); + } } void TestTreeModel::onParseResultReady(const TestParseResultPtr result) @@ -321,12 +366,6 @@ void TestTreeModel::handleParseResult(const TestParseResult *result, TestTreeIte QTC_ASSERT(newItem, return); insertItemInParent(newItem, parentNode, groupingEnabled); - // new items are checked by default - revalidation of parents might be necessary - if (parentNode->checked() != Qt::Checked) { - parentNode->revalidateCheckState(); - const QModelIndex &idx = indexForItem(parentNode); - emit dataChanged(idx, idx); - } } void TestTreeModel::removeAllTestItems() @@ -335,7 +374,7 @@ void TestTreeModel::removeAllTestItems() item->removeChildren(); TestTreeItem *testTreeItem = static_cast(item); if (testTreeItem->checked() == Qt::PartiallyChecked) - testTreeItem->setChecked(Qt::Checked); + testTreeItem->setData(0, Qt::Checked, Qt::CheckStateRole); } emit testTreeModelChanged(); } diff --git a/src/plugins/autotest/testtreemodel.h b/src/plugins/autotest/testtreemodel.h index a47fc9bea77..58c9b279aaa 100644 --- a/src/plugins/autotest/testtreemodel.h +++ b/src/plugins/autotest/testtreemodel.h @@ -87,8 +87,8 @@ private: void removeTestRootNodes(); void removeFiles(const QStringList &files); bool sweepChildren(TestTreeItem *item); - static void insertItemInParent(TestTreeItem *item, TestTreeItem *root, bool groupingEnabled); - + void insertItemInParent(TestTreeItem *item, TestTreeItem *root, bool groupingEnabled); + void revalidateCheckState(TestTreeItem *item); explicit TestTreeModel(QObject *parent = 0); void setupParsingConnections(); diff --git a/src/plugins/autotest/testtreeview.cpp b/src/plugins/autotest/testtreeview.cpp index a6bbe91b909..c8ae2cee074 100644 --- a/src/plugins/autotest/testtreeview.cpp +++ b/src/plugins/autotest/testtreeview.cpp @@ -45,6 +45,13 @@ TestTreeView::TestTreeView(QWidget *parent) Core::ICore::addContextObject(m_context); } +static void changeCheckStateAll(const Qt::CheckState checkState) +{ + TestTreeModel *model = TestTreeModel::instance(); + for (int row = 0, count = model->rowCount(); row < count; ++row) + model->setData(model->index(row, 0), checkState, Qt::CheckStateRole); +} + void TestTreeView::selectAll() { changeCheckStateAll(Qt::Checked); @@ -55,40 +62,5 @@ void TestTreeView::deselectAll() changeCheckStateAll(Qt::Unchecked); } -// this avoids the re-evaluation of parent nodes when modifying the child nodes (setData()) -void TestTreeView::changeCheckStateAll(const Qt::CheckState checkState) -{ - const TestTreeModel *model = TestTreeModel::instance(); - - for (int rootRow = 0; rootRow < model->rowCount(rootIndex()); ++rootRow) { - QModelIndex currentRootIndex = model->index(rootRow, 0, rootIndex()); - if (!currentRootIndex.isValid()) - return; - int count = model->rowCount(currentRootIndex); - QModelIndex last; - for (int classesRow = 0; classesRow < count; ++classesRow) { - const QModelIndex classesIndex = model->index(classesRow, 0, currentRootIndex); - int funcCount = model->rowCount(classesIndex); - TestTreeItem *item = static_cast(classesIndex.internalPointer()); - if (item) { - item->setChecked(checkState); - if (!item->childCount()) - last = classesIndex; - } - for (int functionRow = 0; functionRow < funcCount; ++functionRow) { - last = model->index(functionRow, 0, classesIndex); - TestTreeItem *item = static_cast(last.internalPointer()); - if (item) - item->setChecked(checkState); - } - } - if (count == 0) { - if (auto item = static_cast(currentRootIndex.internalPointer())) - item->setChecked(checkState); - } - emit dataChanged(currentRootIndex, last); - } -} - } // namespace Internal } // namespace Autotest diff --git a/src/plugins/autotest/testtreeview.h b/src/plugins/autotest/testtreeview.h index 631a552912f..1641851cc7a 100644 --- a/src/plugins/autotest/testtreeview.h +++ b/src/plugins/autotest/testtreeview.h @@ -45,7 +45,6 @@ public: void deselectAll(); private: - void changeCheckStateAll(const Qt::CheckState checkState); Core::IContext *m_context; }; diff --git a/src/plugins/clangcodemodel/clangbackendcommunicator.cpp b/src/plugins/clangcodemodel/clangbackendcommunicator.cpp index 193e6dfbff3..9e59ab98a8b 100644 --- a/src/plugins/clangcodemodel/clangbackendcommunicator.cpp +++ b/src/plugins/clangcodemodel/clangbackendcommunicator.cpp @@ -368,26 +368,23 @@ QFuture BackendCommunicator::requestReferences( const FileContainer &fileContainer, quint32 line, quint32 column, - QTextDocument *textDocument, const CppTools::SemanticInfo::LocalUseMap &localUses) { const RequestReferencesMessage message(fileContainer, line, column); m_sender->requestReferences(message); - return m_receiver.addExpectedReferencesMessage(message.ticketNumber(), textDocument, - localUses); + return m_receiver.addExpectedReferencesMessage(message.ticketNumber(), localUses); } QFuture BackendCommunicator::requestLocalReferences( const FileContainer &fileContainer, quint32 line, - quint32 column, - QTextDocument *textDocument) + quint32 column) { const RequestReferencesMessage message(fileContainer, line, column, true); m_sender->requestReferences(message); - return m_receiver.addExpectedReferencesMessage(message.ticketNumber(), textDocument); + return m_receiver.addExpectedReferencesMessage(message.ticketNumber()); } QFuture BackendCommunicator::requestToolTip( diff --git a/src/plugins/clangcodemodel/clangbackendcommunicator.h b/src/plugins/clangcodemodel/clangbackendcommunicator.h index 748f2a00658..941126c7c71 100644 --- a/src/plugins/clangcodemodel/clangbackendcommunicator.h +++ b/src/plugins/clangcodemodel/clangbackendcommunicator.h @@ -75,13 +75,11 @@ public: const FileContainer &fileContainer, quint32 line, quint32 column, - QTextDocument *textDocument, const LocalUseMap &localUses); QFuture requestLocalReferences( const FileContainer &fileContainer, quint32 line, - quint32 column, - QTextDocument *textDocument); + quint32 column); QFuture requestToolTip(const FileContainer &fileContainer, quint32 line, quint32 column); diff --git a/src/plugins/clangcodemodel/clangbackendreceiver.cpp b/src/plugins/clangcodemodel/clangbackendreceiver.cpp index 3794eb0b6ba..306dfb05f1a 100644 --- a/src/plugins/clangcodemodel/clangbackendreceiver.cpp +++ b/src/plugins/clangcodemodel/clangbackendreceiver.cpp @@ -101,16 +101,14 @@ void BackendReceiver::deleteProcessorsOfEditorWidget(TextEditor::TextEditorWidge QFuture BackendReceiver::addExpectedReferencesMessage( quint64 ticket, - QTextDocument *textDocument, const CppTools::SemanticInfo::LocalUseMap &localUses) { - QTC_CHECK(textDocument); QTC_CHECK(!m_referencesTable.contains(ticket)); QFutureInterface futureInterface; futureInterface.reportStarted(); - const ReferencesEntry entry{futureInterface, textDocument, localUses}; + const ReferencesEntry entry{futureInterface, localUses}; m_referencesTable.insert(ticket, entry); return futureInterface.future(); @@ -221,24 +219,17 @@ void BackendReceiver::documentAnnotationsChanged(const DocumentAnnotationsChange } static -CppTools::CursorInfo::Range toCursorInfoRange(const QTextDocument &textDocument, - const SourceRangeContainer &sourceRange) +CppTools::CursorInfo::Range toCursorInfoRange(const SourceRangeContainer &sourceRange) { const SourceLocationContainer start = sourceRange.start(); const SourceLocationContainer end = sourceRange.end(); const unsigned length = end.column() - start.column(); - const QTextBlock block = textDocument.findBlockByNumber(static_cast(start.line()) - 1); - const int shift = ClangCodeModel::Utils::extraUtf8CharsShift(block.text(), - static_cast(start.column())); - const uint column = start.column() - static_cast(shift); - - return CppTools::CursorInfo::Range(start.line(), column, length); + return CppTools::CursorInfo::Range(start.line(), start.column(), length); } static -CppTools::CursorInfo toCursorInfo(const QTextDocument &textDocument, - const CppTools::SemanticInfo::LocalUseMap &localUses, +CppTools::CursorInfo toCursorInfo(const CppTools::SemanticInfo::LocalUseMap &localUses, const ReferencesMessage &message) { CppTools::CursorInfo result; @@ -246,7 +237,7 @@ CppTools::CursorInfo toCursorInfo(const QTextDocument &textDocument, result.areUseRangesForLocalVariable = message.isLocalVariable(); for (const SourceRangeContainer &reference : references) - result.useRanges.append(toCursorInfoRange(textDocument, reference)); + result.useRanges.append(toCursorInfoRange(reference)); result.useRanges.reserve(references.size()); result.localUses = localUses; @@ -284,8 +275,7 @@ void BackendReceiver::references(const ReferencesMessage &message) if (futureInterface.isCanceled()) return; // Editor document closed or a new request was issued making this result outdated. - QTC_ASSERT(entry.textDocument, return); - futureInterface.reportResult(toCursorInfo(*entry.textDocument, entry.localUses, message)); + futureInterface.reportResult(toCursorInfo(entry.localUses, message)); futureInterface.reportFinished(); } diff --git a/src/plugins/clangcodemodel/clangbackendreceiver.h b/src/plugins/clangcodemodel/clangbackendreceiver.h index 921150a52dc..19eeb3ce5bb 100644 --- a/src/plugins/clangcodemodel/clangbackendreceiver.h +++ b/src/plugins/clangcodemodel/clangbackendreceiver.h @@ -56,7 +56,6 @@ public: QFuture addExpectedReferencesMessage(quint64 ticket, - QTextDocument *textDocument, const CppTools::SemanticInfo::LocalUseMap &localUses = CppTools::SemanticInfo::LocalUseMap()); QFuture addExpectedRequestFollowSymbolMessage(quint64 ticket); @@ -82,13 +81,10 @@ private: struct ReferencesEntry { ReferencesEntry() = default; ReferencesEntry(QFutureInterface futureInterface, - QTextDocument *textDocument, const CppTools::SemanticInfo::LocalUseMap &localUses) : futureInterface(futureInterface) - , textDocument(textDocument) , localUses(localUses) {} QFutureInterface futureInterface; - QPointer textDocument; CppTools::SemanticInfo::LocalUseMap localUses; }; QHash m_referencesTable; diff --git a/src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp b/src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp index 644c5d778c9..2a4673f2133 100644 --- a/src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp +++ b/src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp @@ -559,7 +559,8 @@ ClangCompletionAssistProcessor::extractLineColumn(int position) int line = -1, column = -1; ::Utils::Text::convertPosition(m_interface->textDocument(), position, &line, &column); const QTextBlock block = m_interface->textDocument()->findBlock(position); - column += ClangCodeModel::Utils::extraUtf8CharsShift(block.text(), column) + 1; + const QString stringOnTheLeft = block.text().left(column); + column = stringOnTheLeft.toUtf8().size() + 1; // '+ 1' is for 1-based columns return {line, column}; } diff --git a/src/plugins/clangcodemodel/clangdiagnosticmanager.cpp b/src/plugins/clangcodemodel/clangdiagnosticmanager.cpp index eb43f6556ee..261d196b0b4 100644 --- a/src/plugins/clangcodemodel/clangdiagnosticmanager.cpp +++ b/src/plugins/clangcodemodel/clangdiagnosticmanager.cpp @@ -64,8 +64,7 @@ int positionInText(QTextDocument *textDocument, { auto textBlock = textDocument->findBlockByNumber( static_cast(sourceLocationContainer.line()) - 1); - int column = static_cast(sourceLocationContainer.column()) - 1; - column -= ClangCodeModel::Utils::extraUtf8CharsShift(textBlock.text(), column); + const int column = static_cast(sourceLocationContainer.column()) - 1; return textBlock.position() + column; } diff --git a/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp b/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp index 3019664f497..e9dc9162ee0 100644 --- a/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp +++ b/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp @@ -29,6 +29,7 @@ #include "clangdiagnostictooltipwidget.h" #include "clangfixitoperation.h" #include "clangfixitoperationsextractor.h" +#include "clangmodelmanagersupport.h" #include "clangtokeninfosreporter.h" #include "clangprojectsettings.h" #include "clangutils.h" @@ -66,6 +67,12 @@ namespace ClangCodeModel { namespace Internal { +static ClangProjectSettings &getProjectSettings(ProjectExplorer::Project *project) +{ + QTC_CHECK(project); + return ModelManagerSupportClang::instance()->projectSettings(project); +} + ClangEditorDocumentProcessor::ClangEditorDocumentProcessor( BackendCommunicator &communicator, TextEditor::TextDocument *document) @@ -174,6 +181,11 @@ void ClangEditorDocumentProcessor::clearProjectPart() m_projectPart.clear(); } +Core::Id ClangEditorDocumentProcessor::diagnosticConfigId() const +{ + return m_diagnosticConfigId; +} + void ClangEditorDocumentProcessor::updateCodeWarnings( const QVector &diagnostics, const ClangBackEnd::DiagnosticContainer &firstHeaderErrorDiagnostic, @@ -331,20 +343,19 @@ ClangEditorDocumentProcessor::cursorInfo(const CppTools::CursorInfoParams ¶m { int line, column; convertPosition(params.textCursor, &line, &column); - ++column; // for 1-based columns if (!isCursorOnIdentifier(params.textCursor)) return defaultCursorInfoFuture(); const QTextBlock block = params.textCursor.document()->findBlockByNumber(line - 1); - column += ClangCodeModel::Utils::extraUtf8CharsShift(block.text(), column); + const QString stringOnTheLeft = block.text().left(column); + column = stringOnTheLeft.toUtf8().size() + 1; // '+ 1' is for 1-based columns const CppTools::SemanticInfo::LocalUseMap localUses = CppTools::BuiltinCursorInfo::findLocalUses(params.semanticInfo.doc, line, column); return m_communicator.requestReferences(simpleFileContainer(), static_cast(line), static_cast(column), - textDocument(), localUses); } @@ -361,8 +372,7 @@ QFuture ClangEditorDocumentProcessor::requestLocalReferenc return m_communicator.requestLocalReferences(simpleFileContainer(), static_cast(line), - static_cast(column), - textDocument()); + static_cast(column)); } QFuture @@ -437,6 +447,7 @@ public: } const QStringList &options() const { return m_options; } + const Core::Id &diagnosticConfigId() const { return m_diagnosticConfigId; } private: void addLanguageOptions() @@ -458,21 +469,28 @@ private: void addDiagnosticOptions() { if (m_projectPart.project) { - ClangProjectSettings projectSettings(m_projectPart.project); + ClangProjectSettings &projectSettings = getProjectSettings(m_projectPart.project); if (!projectSettings.useGlobalConfig()) { const Core::Id warningConfigId = projectSettings.warningConfigId(); const CppTools::ClangDiagnosticConfigsModel configsModel( CppTools::codeModelSettings()->clangCustomDiagnosticConfigs()); if (configsModel.hasConfigWithId(warningConfigId)) { - m_options.append( - configsModel.configWithId(warningConfigId).commandLineWarnings()); + addDiagnosticOptionsForConfig(configsModel.configWithId(warningConfigId)); return; } } } - m_options.append( - CppTools::codeModelSettings()->clangDiagnosticConfig().commandLineWarnings()); + addDiagnosticOptionsForConfig(CppTools::codeModelSettings()->clangDiagnosticConfig()); + } + + void addDiagnosticOptionsForConfig(const CppTools::ClangDiagnosticConfig &diagnosticConfig) + { + m_diagnosticConfigId = diagnosticConfig.id(); + + m_options.append(diagnosticConfig.clangOptions()); + addClangTidyOptions(diagnosticConfig.clangTidyChecks()); + addClazyOptions(diagnosticConfig.clazyChecks()); } void addXclangArg(const QString &argName, const QString &argValue = QString()) @@ -485,24 +503,22 @@ private: } } - void addTidyOptions() + void addClangTidyOptions(const QString &checks) { - const QString tidyChecks = CppTools::codeModelSettings()->tidyChecks(); - if (tidyChecks.isEmpty()) + if (checks.isEmpty()) return; addXclangArg("-add-plugin", "clang-tidy"); - addXclangArg("-plugin-arg-clang-tidy", "-checks='-*" + tidyChecks + "'"); + addXclangArg("-plugin-arg-clang-tidy", "-checks='-*" + checks + "'"); } - void addClazyOptions() + void addClazyOptions(const QString &checks) { - const QString clazyChecks = CppTools::codeModelSettings()->clazyChecks(); - if (clazyChecks.isEmpty()) + if (checks.isEmpty()) return; addXclangArg("-add-plugin", "clang-lazy"); - addXclangArg("-plugin-arg-clang-lazy", clazyChecks); + addXclangArg("-plugin-arg-clang-lazy", checks); // NOTE: we already use -isystem for all include paths to make libclang skip diagnostics for // all of them. That means that ignore-included-files will not change anything unless we decide @@ -515,10 +531,7 @@ private: if (!m_projectPart.project) m_options.append(ClangProjectSettings::globalCommandLineOptions()); else - m_options.append(ClangProjectSettings{m_projectPart.project}.commandLineOptions()); - - addTidyOptions(); - addClazyOptions(); + m_options.append(getProjectSettings(m_projectPart.project).commandLineOptions()); } void addPrecompiledHeaderOptions() @@ -541,6 +554,7 @@ private: const QString &m_filePath; const CppTools::ProjectPart &m_projectPart; + Core::Id m_diagnosticConfigId; QStringList m_options; }; } // namespace @@ -563,6 +577,7 @@ void ClangEditorDocumentProcessor::registerTranslationUnitForEditor( } const FileOptionsBuilder fileOptions(filePath(), projectPart); + m_diagnosticConfigId = fileOptions.diagnosticConfigId(); m_communicator.registerTranslationUnitsForEditor( {fileContainerWithOptionsAndDocumentContent(projectPart, fileOptions.options())}); ClangCodeModel::Utils::setLastSentDocumentRevision(filePath(), revision()); diff --git a/src/plugins/clangcodemodel/clangeditordocumentprocessor.h b/src/plugins/clangcodemodel/clangeditordocumentprocessor.h index 67ef0bc8a5d..8715bbad082 100644 --- a/src/plugins/clangcodemodel/clangeditordocumentprocessor.h +++ b/src/plugins/clangcodemodel/clangeditordocumentprocessor.h @@ -28,6 +28,7 @@ #include "clangdiagnosticmanager.h" #include "clangeditordocumentparser.h" +#include #include #include @@ -67,6 +68,8 @@ public: CppTools::ProjectPart::Ptr projectPart() const; void clearProjectPart(); + Core::Id diagnosticConfigId() const; + void updateCodeWarnings(const QVector &diagnostics, const ClangBackEnd::DiagnosticContainer &firstHeaderErrorDiagnostic, uint documentRevision); @@ -120,6 +123,7 @@ private: BackendCommunicator &m_communicator; QSharedPointer m_parser; CppTools::ProjectPart::Ptr m_projectPart; + Core::Id m_diagnosticConfigId; bool m_isProjectFile = false; QFutureWatcher m_parserWatcher; QTimer m_updateTranslationUnitTimer; diff --git a/src/plugins/clangcodemodel/clanghoverhandler.cpp b/src/plugins/clangcodemodel/clanghoverhandler.cpp index 5903b182467..1c387562612 100644 --- a/src/plugins/clangcodemodel/clanghoverhandler.cpp +++ b/src/plugins/clangcodemodel/clanghoverhandler.cpp @@ -133,7 +133,10 @@ void ClangHoverHandler::identifyMatch(TextEditorWidget *editorWidget, m_reportPriority = report; m_futureWatcher.reset(new QFutureWatcher()); QObject::connect(m_futureWatcher.data(), &QFutureWatcherBase::finished, [this]() { - processToolTipInfo(m_futureWatcher->result()); + if (m_futureWatcher->isCanceled()) + m_reportPriority(Priority_None); + else + processToolTipInfo(m_futureWatcher->result()); }); m_futureWatcher->setFuture(future); return; diff --git a/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp b/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp index f4813c6eb69..0371b3a06f5 100644 --- a/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp +++ b/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp @@ -30,22 +30,27 @@ #include "clangutils.h" #include "clangfollowsymbol.h" #include "clanghoverhandler.h" +#include "clangprojectsettings.h" #include "clangrefactoringengine.h" #include "clangcurrentdocumentfilter.h" #include +#include #include #include +#include #include #include #include #include +#include #include #include #include +#include #include #include @@ -100,11 +105,22 @@ ModelManagerSupportClang::ModelManagerSupportClang() connect(modelManager, &CppTools::CppModelManager::projectPartsRemoved, this, &ModelManagerSupportClang::onProjectPartsRemoved); + auto *sessionManager = ProjectExplorer::SessionManager::instance(); + connect(sessionManager, &ProjectExplorer::SessionManager::projectAdded, + this, &ModelManagerSupportClang::onProjectAdded); + connect(sessionManager, &ProjectExplorer::SessionManager::aboutToRemoveProject, + this, &ModelManagerSupportClang::onAboutToRemoveProject); + + CppTools::CppCodeModelSettings *settings = CppTools::codeModelSettings().data(); + connect(settings, &CppTools::CppCodeModelSettings::clangDiagnosticConfigsInvalidated, + this, &ModelManagerSupportClang::onDiagnosticConfigsInvalidated); + m_communicator.registerFallbackProjectPart(); } ModelManagerSupportClang::~ModelManagerSupportClang() { + QTC_CHECK(m_projectSettings.isEmpty()); m_instance = 0; } @@ -336,6 +352,52 @@ void ModelManagerSupportClang::onTextMarkContextMenuRequested(TextEditor::TextEd } } +using ClangEditorDocumentProcessors = QVector; +static ClangEditorDocumentProcessors clangProcessors() +{ + ClangEditorDocumentProcessors result; + foreach (auto *editorDocument, cppModelManager()->cppEditorDocuments()) + result.append(qobject_cast(editorDocument->processor())); + + return result; +} + +static ClangEditorDocumentProcessors +clangProcessorsWithProject(const ProjectExplorer::Project *project) +{ + return ::Utils::filtered(clangProcessors(), [project](ClangEditorDocumentProcessor *p) { + return p->hasProjectPart() && p->projectPart()->project == project; + }); +} + +static void updateProcessors(const ClangEditorDocumentProcessors &processors) +{ + CppTools::CppModelManager *modelManager = cppModelManager(); + for (ClangEditorDocumentProcessor *processor : processors) + modelManager->cppEditorDocument(processor->filePath())->resetProcessor(); + modelManager->updateCppEditorDocuments(/*projectsUpdated=*/ false); +} + +void ModelManagerSupportClang::onProjectAdded(ProjectExplorer::Project *project) +{ + QTC_ASSERT(!m_projectSettings.value(project), return); + + auto *settings = new Internal::ClangProjectSettings(project); + connect(settings, &Internal::ClangProjectSettings::changed, [project]() { + updateProcessors(clangProcessorsWithProject(project)); + }); + + m_projectSettings.insert(project, settings); +} + +void ModelManagerSupportClang::onAboutToRemoveProject(ProjectExplorer::Project *project) +{ + ClangProjectSettings * const settings = m_projectSettings.value(project); + QTC_ASSERT(settings, return); + m_projectSettings.remove(project); + delete settings; +} + void ModelManagerSupportClang::onProjectPartsUpdated(ProjectExplorer::Project *project) { QTC_ASSERT(project, return); @@ -355,21 +417,25 @@ void ModelManagerSupportClang::onProjectPartsRemoved(const QStringList &projectP } } -static QVector +static ClangEditorDocumentProcessors clangProcessorsWithDiagnosticConfig( + const QVector &configIds) +{ + return ::Utils::filtered(clangProcessors(), [configIds](ClangEditorDocumentProcessor *p) { + return configIds.contains(p->diagnosticConfigId()); + }); +} + +void ModelManagerSupportClang::onDiagnosticConfigsInvalidated(const QVector &configIds) +{ + updateProcessors(clangProcessorsWithDiagnosticConfig(configIds)); +} + +static ClangEditorDocumentProcessors clangProcessorsWithProjectParts(const QStringList &projectPartIds) { - QVector result; - - foreach (auto *editorDocument, cppModelManager()->cppEditorDocuments()) { - auto *processor = editorDocument->processor(); - auto *clangProcessor = qobject_cast(processor); - if (clangProcessor && clangProcessor->hasProjectPart()) { - if (projectPartIds.contains(clangProcessor->projectPart()->id())) - result.append(clangProcessor); - } - } - - return result; + return ::Utils::filtered(clangProcessors(), [projectPartIds](ClangEditorDocumentProcessor *p) { + return p->hasProjectPart() && projectPartIds.contains(p->projectPart()->id()); + }); } void ModelManagerSupportClang::unregisterTranslationUnitsWithProjectParts( @@ -398,6 +464,12 @@ QString ModelManagerSupportClang::dummyUiHeaderOnDiskPath(const QString &filePat return m_uiHeaderOnDiskManager.mapPath(filePath); } +ClangProjectSettings &ModelManagerSupportClang::projectSettings( + ProjectExplorer::Project *project) const +{ + return *m_projectSettings.value(project); +} + QString ModelManagerSupportClang::dummyUiHeaderOnDiskDirPath() const { return m_uiHeaderOnDiskManager.directoryPath(); diff --git a/src/plugins/clangcodemodel/clangmodelmanagersupport.h b/src/plugins/clangcodemodel/clangmodelmanagersupport.h index 3744905b420..d8c3e1c9176 100644 --- a/src/plugins/clangcodemodel/clangmodelmanagersupport.h +++ b/src/plugins/clangcodemodel/clangmodelmanagersupport.h @@ -40,7 +40,10 @@ class QMenu; class QWidget; QT_END_NAMESPACE -namespace Core { class IDocument; } +namespace Core { +class IDocument; +class Id; +} // namespace Core namespace TextEditor { class TextEditorWidget; } namespace CppTools { class FollowSymbolInterface; @@ -50,6 +53,8 @@ class RefactoringEngineInterface; namespace ClangCodeModel { namespace Internal { +class ClangProjectSettings; + class ModelManagerSupportClang: public QObject, public CppTools::ModelManagerSupport @@ -71,6 +76,8 @@ public: QString dummyUiHeaderOnDiskDirPath() const; QString dummyUiHeaderOnDiskPath(const QString &filePath) const; + ClangProjectSettings &projectSettings(ProjectExplorer::Project *project) const; + static ModelManagerSupportClang *instance(); private: @@ -93,9 +100,14 @@ private: int lineNumber, QMenu *menu); + void onProjectAdded(ProjectExplorer::Project *project); + void onAboutToRemoveProject(ProjectExplorer::Project *project); + void onProjectPartsUpdated(ProjectExplorer::Project *project); void onProjectPartsRemoved(const QStringList &projectPartIds); + void onDiagnosticConfigsInvalidated(const QVector &configIds); + void unregisterTranslationUnitsWithProjectParts(const QStringList &projectPartIds); void connectTextDocumentToTranslationUnit(TextEditor::TextDocument *textDocument); @@ -111,6 +123,8 @@ private: ClangCompletionAssistProvider m_completionAssistProvider; std::unique_ptr m_followSymbol; std::unique_ptr m_refactoringEngine; + + QHash m_projectSettings; }; class ModelManagerSupportProviderClang : public CppTools::ModelManagerSupportProvider diff --git a/src/plugins/clangcodemodel/clangprojectsettings.cpp b/src/plugins/clangcodemodel/clangprojectsettings.cpp index 2668ee39985..698447cc4b8 100644 --- a/src/plugins/clangcodemodel/clangprojectsettings.cpp +++ b/src/plugins/clangcodemodel/clangprojectsettings.cpp @@ -42,6 +42,25 @@ static QString warningConfigIdKey() static QString customCommandLineKey() { return QLatin1String("ClangCodeModel.CustomCommandLineKey"); } +static bool useGlobalConfigFromSettings(ProjectExplorer::Project *project) +{ + const QVariant useGlobalConfigVariant = project->namedSettings(useGlobalConfigKey()); + return useGlobalConfigVariant.isValid() ? useGlobalConfigVariant.toBool() : true; +} + +static Core::Id warningConfigIdFromSettings(ProjectExplorer::Project *project) +{ + return Core::Id::fromSetting(project->namedSettings(warningConfigIdKey())); +} + +static QStringList customCommandLineFromSettings(ProjectExplorer::Project *project) +{ + QStringList options = project->namedSettings(customCommandLineKey()).toStringList(); + if (options.empty()) + options = ClangProjectSettings::globalCommandLineOptions(); + return options; +} + ClangProjectSettings::ClangProjectSettings(ProjectExplorer::Project *project) : m_project(project) { @@ -88,23 +107,27 @@ void ClangProjectSettings::setCommandLineOptions(const QStringList &options) void ClangProjectSettings::load() { - const QVariant useGlobalConfigVariant = m_project->namedSettings(useGlobalConfigKey()); - const bool useGlobalConfig = useGlobalConfigVariant.isValid() - ? useGlobalConfigVariant.toBool() - : true; - - setUseGlobalConfig(useGlobalConfig); - setWarningConfigId(Core::Id::fromSetting(m_project->namedSettings(warningConfigIdKey()))); - m_customCommandLineOptions = m_project->namedSettings(customCommandLineKey()).toStringList(); - if (m_customCommandLineOptions.empty()) - m_customCommandLineOptions = globalCommandLineOptions(); + setUseGlobalConfig(useGlobalConfigFromSettings(m_project)); + setWarningConfigId(warningConfigIdFromSettings(m_project)); + m_customCommandLineOptions = customCommandLineFromSettings(m_project); } void ClangProjectSettings::store() { + bool settingsChanged = false; + if (useGlobalConfig() != useGlobalConfigFromSettings(m_project)) + settingsChanged = true; + if (warningConfigId() != warningConfigIdFromSettings(m_project)) + settingsChanged = true; + if (commandLineOptions() != customCommandLineFromSettings(m_project)) + settingsChanged = true; + m_project->setNamedSettings(useGlobalConfigKey(), useGlobalConfig()); m_project->setNamedSettings(warningConfigIdKey(), warningConfigId().toSetting()); m_project->setNamedSettings(customCommandLineKey(), m_customCommandLineOptions); + + if (settingsChanged) + emit changed(); } QStringList ClangProjectSettings::globalCommandLineOptions() diff --git a/src/plugins/clangcodemodel/clangprojectsettings.h b/src/plugins/clangcodemodel/clangprojectsettings.h index 01aabfb6e98..0b591b6ccb3 100644 --- a/src/plugins/clangcodemodel/clangprojectsettings.h +++ b/src/plugins/clangcodemodel/clangprojectsettings.h @@ -59,6 +59,9 @@ public: static QStringList globalCommandLineOptions(); +signals: + void changed(); + private: ProjectExplorer::Project *m_project; bool m_useGlobalConfig = true; diff --git a/src/plugins/clangcodemodel/clangprojectsettingswidget.cpp b/src/plugins/clangcodemodel/clangprojectsettingswidget.cpp index d8148a158da..fcee2b1dd85 100644 --- a/src/plugins/clangcodemodel/clangprojectsettingswidget.cpp +++ b/src/plugins/clangcodemodel/clangprojectsettingswidget.cpp @@ -25,6 +25,7 @@ #include "clangprojectsettingswidget.h" +#include "clangmodelmanagersupport.h" #include "clangprojectsettings.h" #include @@ -52,7 +53,7 @@ static Core::Id configIdForProject(ClangProjectSettings &projectSettings) } ClangProjectSettingsWidget::ClangProjectSettingsWidget(ProjectExplorer::Project *project) - : m_projectSettings(project) + : m_projectSettings(ModelManagerSupportClang::instance()->projectSettings(project)) { m_ui.setupUi(this); @@ -76,6 +77,8 @@ ClangProjectSettingsWidget::ClangProjectSettingsWidget(ProjectExplorer::Project connect(m_ui.clangSettings, static_cast(&QComboBox::currentIndexChanged), this, &ClangProjectSettingsWidget::onClangSettingsChanged); + connect(project, &ProjectExplorer::Project::aboutToSaveSettings, + this, &ClangProjectSettingsWidget::onAboutToSaveProjectSettings); m_ui.diagnosticConfigurationGroupBox->layout()->addWidget(m_diagnosticConfigWidget); } @@ -86,7 +89,6 @@ void ClangProjectSettingsWidget::onCurrentWarningConfigChanged(const Core::Id &c if (m_projectSettings.useGlobalConfig()) return; m_projectSettings.setWarningConfigId(currentConfigId); - m_projectSettings.store(); } void ClangProjectSettingsWidget::onCustomWarningConfigsChanged( @@ -97,7 +99,6 @@ void ClangProjectSettingsWidget::onCustomWarningConfigsChanged( const QSharedPointer codeModelSettings = CppTools::codeModelSettings(); codeModelSettings->setClangCustomDiagnosticConfigs(customConfigs); - codeModelSettings->toSettings(Core::ICore::settings()); connectToCppCodeModelSettingsChanged(); } @@ -115,16 +116,19 @@ void ClangProjectSettingsWidget::onDelayedTemplateParseClicked(bool checked) options.removeAll(QLatin1String{ClangProjectSettings::NoDelayedTemplateParsing}); options.append(extraFlag); m_projectSettings.setCommandLineOptions(options); - m_projectSettings.store(); } void ClangProjectSettingsWidget::onClangSettingsChanged(int index) { m_projectSettings.setUseGlobalConfig(index == 0 ? true : false); - m_projectSettings.store(); syncOtherWidgetsToComboBox(); } +void ClangProjectSettingsWidget::onAboutToSaveProjectSettings() +{ + CppTools::codeModelSettings()->toSettings(Core::ICore::settings()); +} + void ClangProjectSettingsWidget::syncOtherWidgetsToComboBox() { const QStringList options = m_projectSettings.commandLineOptions(); diff --git a/src/plugins/clangcodemodel/clangprojectsettingswidget.h b/src/plugins/clangcodemodel/clangprojectsettingswidget.h index d27be6341e8..57d5d1210bb 100644 --- a/src/plugins/clangcodemodel/clangprojectsettingswidget.h +++ b/src/plugins/clangcodemodel/clangprojectsettingswidget.h @@ -51,6 +51,7 @@ private: void onCustomWarningConfigsChanged(const CppTools::ClangDiagnosticConfigs &customConfigs); void onDelayedTemplateParseClicked(bool); void onClangSettingsChanged(int index); + void onAboutToSaveProjectSettings(); void refreshDiagnosticConfigsWidgetFromSettings(); void connectToCppCodeModelSettingsChanged(); void disconnectFromCppCodeModelSettingsChanged(); @@ -58,7 +59,7 @@ private: private: Ui::ClangProjectSettingsWidget m_ui; - ClangProjectSettings m_projectSettings; + ClangProjectSettings &m_projectSettings; QPointer m_diagnosticConfigWidget; }; diff --git a/src/plugins/clangcodemodel/clangutils.cpp b/src/plugins/clangcodemodel/clangutils.cpp index dea79f66250..cf659ff4046 100644 --- a/src/plugins/clangcodemodel/clangutils.cpp +++ b/src/plugins/clangcodemodel/clangutils.cpp @@ -190,31 +190,5 @@ void setLastSentDocumentRevision(const QString &filePath, uint revision) document->sendTracker().setLastSentRevision(int(revision)); } -// CLANG-UPGRADE-CHECK: Workaround still needed? -// Remove once clang reports correct columns for lines with multi-byte utf8. -int extraUtf8CharsShift(const QString &str, int column) -{ - int shift = 0; - const QByteArray byteArray = str.toUtf8(); - for (int i = 0; i < qMin(str.length(), column); ++i) { - const uchar firstByte = static_cast(byteArray.at(i)); - // Skip different amount of bytes depending on value - if (firstByte < 0xC0) { - continue; - } else if (firstByte < 0xE0) { - ++shift; - ++i; - } else if (firstByte < 0xF0) { - shift += 2; - i += 2; - } else { - shift += 3; - i += 3; - } - } - return shift; -} - - } // namespace Utils } // namespace Clang diff --git a/src/plugins/clangcodemodel/clangutils.h b/src/plugins/clangcodemodel/clangutils.h index 6529af2b2c3..edd26ba7552 100644 --- a/src/plugins/clangcodemodel/clangutils.h +++ b/src/plugins/clangcodemodel/clangutils.h @@ -47,7 +47,5 @@ CppTools::ProjectPart::Ptr projectPartForFileBasedOnProcessor(const QString &fil bool isProjectPartLoaded(const CppTools::ProjectPart::Ptr projectPart); QString projectPartIdForFile(const QString &filePath); -int extraUtf8CharsShift(const QString &str, int column); - } // namespace Utils } // namespace Clang diff --git a/src/plugins/cmakeprojectmanager/servermodereader.cpp b/src/plugins/cmakeprojectmanager/servermodereader.cpp index f4a6235e767..20817562751 100644 --- a/src/plugins/cmakeprojectmanager/servermodereader.cpp +++ b/src/plugins/cmakeprojectmanager/servermodereader.cpp @@ -460,7 +460,6 @@ int ServerModeReader::calculateProgress(const int minRange, const int min, const void ServerModeReader::extractCodeModelData(const QVariantMap &data) { const QVariantList configs = data.value("configurations").toList(); - QTC_CHECK(configs.count() == 1); // FIXME: Support several configurations! for (const QVariant &c : configs) { const QVariantMap &cData = c.toMap(); extractConfigurationData(cData); @@ -842,6 +841,11 @@ void ServerModeReader::addFileGroups(ProjectNode *targetRoot, { QList toList; QSet alreadyListed; + // Files already added by other configurations: + targetRoot->forEachGenericNode([&alreadyListed](const Node *n) { + alreadyListed.insert(n->filePath()); + }); + for (const FileGroup *f : fileGroups) { const QList newSources = Utils::filtered(f->sources, [&alreadyListed](const Utils::FileName &fn) { const int count = alreadyListed.count(); diff --git a/src/plugins/cpptools/baseeditordocumentprocessor.h b/src/plugins/cpptools/baseeditordocumentprocessor.h index d799c636b25..1b63cbd64dd 100644 --- a/src/plugins/cpptools/baseeditordocumentprocessor.h +++ b/src/plugins/cpptools/baseeditordocumentprocessor.h @@ -93,6 +93,8 @@ public: virtual QFuture requestFollowSymbol(int line, int column) = 0; virtual QFuture toolTipInfo(const QByteArray &codecName, int line, int column); + QString filePath() const { return m_filePath; } + public: using HeaderErrorDiagnosticWidgetCreator = std::function; @@ -117,7 +119,6 @@ protected: BaseEditorDocumentParser::UpdateParams updateParams); // Convenience - QString filePath() const { return m_filePath; } unsigned revision() const { return static_cast(m_textDocument->revision()); } QTextDocument *textDocument() const { return m_textDocument; } diff --git a/src/plugins/cpptools/clangdiagnosticconfig.cpp b/src/plugins/cpptools/clangdiagnosticconfig.cpp index 89cc76442ad..c605d128008 100644 --- a/src/plugins/cpptools/clangdiagnosticconfig.cpp +++ b/src/plugins/cpptools/clangdiagnosticconfig.cpp @@ -47,14 +47,14 @@ void ClangDiagnosticConfig::setDisplayName(const QString &displayName) m_displayName = displayName; } -QStringList ClangDiagnosticConfig::commandLineWarnings() const +QStringList ClangDiagnosticConfig::clangOptions() const { - return m_commandLineWarnings; + return m_clangOptions; } -void ClangDiagnosticConfig::setCommandLineWarnings(const QStringList &warnings) +void ClangDiagnosticConfig::setClangOptions(const QStringList &options) { - m_commandLineWarnings = warnings; + m_clangOptions = options; } bool ClangDiagnosticConfig::isReadOnly() const @@ -71,8 +71,35 @@ bool ClangDiagnosticConfig::operator==(const ClangDiagnosticConfig &other) const { return m_id == other.m_id && m_displayName == other.m_displayName - && m_commandLineWarnings == other.m_commandLineWarnings + && m_clangOptions == other.m_clangOptions + && m_clangTidyChecks == other.m_clangTidyChecks + && m_clazyChecks == other.m_clazyChecks && m_isReadOnly == other.m_isReadOnly; } +bool ClangDiagnosticConfig::operator!=(const ClangDiagnosticConfig &other) const +{ + return !(*this == other); +} + +QString ClangDiagnosticConfig::clangTidyChecks() const +{ + return m_clangTidyChecks; +} + +void ClangDiagnosticConfig::setClangTidyChecks(const QString &checks) +{ + m_clangTidyChecks = checks; +} + +QString ClangDiagnosticConfig::clazyChecks() const +{ + return m_clazyChecks; +} + +void ClangDiagnosticConfig::setClazyChecks(const QString &checks) +{ + m_clazyChecks = checks; +} + } // namespace CppTools diff --git a/src/plugins/cpptools/clangdiagnosticconfig.h b/src/plugins/cpptools/clangdiagnosticconfig.h index b9efb040b0e..327d2f504ea 100644 --- a/src/plugins/cpptools/clangdiagnosticconfig.h +++ b/src/plugins/cpptools/clangdiagnosticconfig.h @@ -43,18 +43,27 @@ public: QString displayName() const; void setDisplayName(const QString &displayName); - QStringList commandLineWarnings() const; - void setCommandLineWarnings(const QStringList &commandLineWarnings); + QStringList clangOptions() const; + void setClangOptions(const QStringList &options); + + QString clangTidyChecks() const; + void setClangTidyChecks(const QString &checks); + + QString clazyChecks() const; + void setClazyChecks(const QString &checks); bool isReadOnly() const; void setIsReadOnly(bool isReadOnly); bool operator==(const ClangDiagnosticConfig &other) const; + bool operator!=(const ClangDiagnosticConfig &other) const; private: Core::Id m_id; QString m_displayName; - QStringList m_commandLineWarnings; + QStringList m_clangOptions; + QString m_clangTidyChecks; + QString m_clazyChecks; bool m_isReadOnly = false; }; diff --git a/src/plugins/cpptools/clangdiagnosticconfigsmodel.cpp b/src/plugins/cpptools/clangdiagnosticconfigsmodel.cpp index 206a0d8baab..4580e82801d 100644 --- a/src/plugins/cpptools/clangdiagnosticconfigsmodel.cpp +++ b/src/plugins/cpptools/clangdiagnosticconfigsmodel.cpp @@ -45,7 +45,7 @@ static void addConfigForQuestionableConstructs(ClangDiagnosticConfigsModel &mode config.setDisplayName(QCoreApplication::translate("ClangDiagnosticConfigsModel", "Warnings for questionable constructs")); config.setIsReadOnly(true); - config.setCommandLineWarnings(QStringList{ + config.setClangOptions(QStringList{ QStringLiteral("-Wall"), QStringLiteral("-Wextra"), } + commonWarnings()); @@ -60,7 +60,7 @@ static void addConfigForPedanticWarnings(ClangDiagnosticConfigsModel &model) config.setDisplayName(QCoreApplication::translate("ClangDiagnosticConfigsModel", "Pedantic Warnings")); config.setIsReadOnly(true); - config.setCommandLineWarnings(QStringList{QStringLiteral("-Wpedantic")} + commonWarnings()); + config.setClangOptions(QStringList{QStringLiteral("-Wpedantic")} + commonWarnings()); model.appendOrUpdate(config); } @@ -72,7 +72,7 @@ static void addConfigForAlmostEveryWarning(ClangDiagnosticConfigsModel &model) config.setDisplayName(QCoreApplication::translate("ClangDiagnosticConfigsModel", "Warnings for almost everything")); config.setIsReadOnly(true); - config.setCommandLineWarnings(QStringList{ + config.setClangOptions(QStringList{ QStringLiteral("-Weverything"), QStringLiteral("-Wno-c++98-compat"), QStringLiteral("-Wno-c++98-compat-pedantic"), @@ -158,6 +158,23 @@ ClangDiagnosticConfigsModel::displayNameWithBuiltinIndication(const ClangDiagnos : config.displayName(); } +QVector ClangDiagnosticConfigsModel::changedOrRemovedConfigs( + const ClangDiagnosticConfigs &oldConfigs, const ClangDiagnosticConfigs &newConfigs) +{ + ClangDiagnosticConfigsModel newConfigsModel(newConfigs); + QVector changedConfigs; + + for (const ClangDiagnosticConfig &old: oldConfigs) { + const int i = newConfigsModel.indexOfConfig(old.id()); + if (i == -1) + changedConfigs.append(old.id()); // Removed + else if (newConfigsModel.configs()[i] != old) + changedConfigs.append(old.id()); // Changed + } + + return changedConfigs; +} + int ClangDiagnosticConfigsModel::indexOfConfig(const Core::Id &id) const { return Utils::indexOf(m_diagnosticConfigs, [&](const ClangDiagnosticConfig &config) { diff --git a/src/plugins/cpptools/clangdiagnosticconfigsmodel.h b/src/plugins/cpptools/clangdiagnosticconfigsmodel.h index 14ef823f3d2..c6f4022526f 100644 --- a/src/plugins/cpptools/clangdiagnosticconfigsmodel.h +++ b/src/plugins/cpptools/clangdiagnosticconfigsmodel.h @@ -29,6 +29,8 @@ #include "clangdiagnosticconfig.h" +#include + namespace CppTools { class CPPTOOLS_EXPORT ClangDiagnosticConfigsModel @@ -47,11 +49,11 @@ public: ClangDiagnosticConfigs configs() const; bool hasConfigWithId(const Core::Id &id) const; const ClangDiagnosticConfig &configWithId(const Core::Id &id) const; + int indexOfConfig(const Core::Id &id) const; static QString displayNameWithBuiltinIndication(const ClangDiagnosticConfig &config); - -private: - int indexOfConfig(const Core::Id &id) const; + static QVector changedOrRemovedConfigs(const ClangDiagnosticConfigs &oldConfigs, + const ClangDiagnosticConfigs &newConfigs); private: ClangDiagnosticConfigs m_diagnosticConfigs; diff --git a/src/plugins/cpptools/clangdiagnosticconfigswidget.cpp b/src/plugins/cpptools/clangdiagnosticconfigswidget.cpp index 288b5e3a8d7..1cc623e3536 100644 --- a/src/plugins/cpptools/clangdiagnosticconfigswidget.cpp +++ b/src/plugins/cpptools/clangdiagnosticconfigswidget.cpp @@ -25,6 +25,8 @@ #include "clangdiagnosticconfigswidget.h" #include "ui_clangdiagnosticconfigswidget.h" +#include "ui_clazychecks.h" +#include "ui_tidychecks.h" #include #include @@ -45,6 +47,7 @@ ClangDiagnosticConfigsWidget::ClangDiagnosticConfigsWidget( , m_diagnosticConfigsModel(diagnosticConfigsModel) { m_ui->setupUi(this); + setupPluginsWidgets(); connectConfigChooserCurrentIndex(); connect(m_ui->copyButton, &QPushButton::clicked, @@ -108,6 +111,18 @@ void ClangDiagnosticConfigsWidget::onRemoveButtonClicked() syncConfigChooserToModel(); } +void ClangDiagnosticConfigsWidget::onClangTidyItemChanged(QListWidgetItem *item) +{ + const QString prefix = item->text(); + ClangDiagnosticConfig config = currentConfig(); + QString checks = config.clangTidyChecks(); + item->checkState() == Qt::Checked + ? checks.append(',' + prefix) + : checks.remove(',' + prefix); + config.setClangTidyChecks(checks); + updateConfig(config); +} + static bool isAcceptedWarningOption(const QString &option) { return option == "-w" @@ -162,10 +177,8 @@ void ClangDiagnosticConfigsWidget::onDiagnosticOptionsEdited() // Commit valid changes ClangDiagnosticConfig updatedConfig = currentConfig(); - updatedConfig.setCommandLineWarnings(normalizedOptions); - - m_diagnosticConfigsModel.appendOrUpdate(updatedConfig); - emit customConfigsChanged(customConfigs()); + updatedConfig.setClangOptions(normalizedOptions); + updateConfig(updatedConfig); } void ClangDiagnosticConfigsWidget::syncWidgetsToModel(const Core::Id &configToSelect) @@ -213,12 +226,74 @@ void ClangDiagnosticConfigsWidget::syncOtherWidgetsToComboBox() // Update main button row m_ui->removeButton->setEnabled(!config.isReadOnly()); - // Update child widgets + // Update Text Edit const QString options = m_notAcceptedOptions.contains(config.id()) ? m_notAcceptedOptions.value(config.id()) - : config.commandLineWarnings().join(QLatin1Char(' ')); + : config.clangOptions().join(QLatin1Char(' ')); setDiagnosticOptions(options); m_ui->diagnosticOptionsTextEdit->setReadOnly(config.isReadOnly()); + + syncClangTidyWidgets(config); + syncClazyWidgets(config); +} + +void ClangDiagnosticConfigsWidget::syncClangTidyWidgets(const ClangDiagnosticConfig &config) +{ + disconnectClangTidyItemChanged(); + + const QString tidyChecks = config.clangTidyChecks(); + for (int row = 0; row < m_tidyChecks->checksList->count(); ++row) { + QListWidgetItem *item = m_tidyChecks->checksList->item(row); + + Qt::ItemFlags flags = item->flags(); + flags |= Qt::ItemIsUserCheckable; + if (config.isReadOnly()) + flags &= ~Qt::ItemIsEnabled; + else + flags |= Qt::ItemIsEnabled; + item->setFlags(flags); + + if (tidyChecks.indexOf(item->text()) != -1) + item->setCheckState(Qt::Checked); + else + item->setCheckState(Qt::Unchecked); + } + + connectClangTidyItemChanged(); +} + +void ClangDiagnosticConfigsWidget::syncClazyWidgets(const ClangDiagnosticConfig &config) +{ + const QString clazyChecks = config.clazyChecks(); + if (clazyChecks.isEmpty()) + m_clazyChecks->clazyLevel->setCurrentIndex(0); + else + m_clazyChecks->clazyLevel->setCurrentText(clazyChecks); + m_clazyChecksWidget->setEnabled(!config.isReadOnly()); +} + +void ClangDiagnosticConfigsWidget::setClazyLevelDescription(int index) +{ + // Levels descriptions are taken from https://github.com/KDE/clazy + static const QString levelDescriptions[] { + QString(), + tr("Very stable checks, 99.99% safe, no false-positives."), + tr("Similar to level 0, but sometimes (rarely) there might be\n" + "some false-positives."), + tr("Sometimes has false-positives (20-30%)."), + tr("Not always correct, possibly very noisy, might require\n" + "a knowledgeable developer to review, might have a very big\n" + "rate of false-positives, might have bugs.") + }; + + QTC_ASSERT(m_clazyChecks, return); + m_clazyChecks->levelDescription->setText(levelDescriptions[static_cast(index)]); +} + +void ClangDiagnosticConfigsWidget::updateConfig(const ClangDiagnosticConfig &config) +{ + m_diagnosticConfigsModel.appendOrUpdate(config); + emit customConfigsChanged(customConfigs()); } bool ClangDiagnosticConfigsWidget::isConfigChooserEmpty() const @@ -264,6 +339,18 @@ void ClangDiagnosticConfigsWidget::updateValidityWidgets(const QString &errorMes m_ui->validationResultLabel->setStyleSheet(styleSheet); } +void ClangDiagnosticConfigsWidget::connectClangTidyItemChanged() +{ + connect(m_tidyChecks->checksList, &QListWidget::itemChanged, + this, &ClangDiagnosticConfigsWidget::onClangTidyItemChanged); +} + +void ClangDiagnosticConfigsWidget::disconnectClangTidyItemChanged() +{ + disconnect(m_tidyChecks->checksList, &QListWidget::itemChanged, + this, &ClangDiagnosticConfigsWidget::onClangTidyItemChanged); +} + void ClangDiagnosticConfigsWidget::connectConfigChooserCurrentIndex() { connect(m_ui->configChooserComboBox, @@ -314,4 +401,31 @@ void ClangDiagnosticConfigsWidget::refresh( syncWidgetsToModel(configToSelect); } +void ClangDiagnosticConfigsWidget::setupPluginsWidgets() +{ + m_clazyChecks.reset(new CppTools::Ui::ClazyChecks); + m_clazyChecksWidget = new QWidget(); + m_clazyChecks->setupUi(m_clazyChecksWidget); + connect(m_clazyChecks->clazyLevel, + static_cast(&QComboBox::currentIndexChanged), + [this](int index) { + setClazyLevelDescription(index); + ClangDiagnosticConfig config = currentConfig(); + if (index == 0) + config.setClazyChecks(QString()); + else + config.setClazyChecks(m_clazyChecks->clazyLevel->itemText(index)); + updateConfig(config); + }); + + m_tidyChecks.reset(new CppTools::Ui::TidyChecks); + m_tidyChecksWidget = new QWidget(); + m_tidyChecks->setupUi(m_tidyChecksWidget); + connectClangTidyItemChanged(); + + m_ui->pluginChecksTabs->addTab(m_tidyChecksWidget, tr("Clang-Tidy")); + m_ui->pluginChecksTabs->addTab(m_clazyChecksWidget, tr("Clazy")); + m_ui->pluginChecksTabs->setCurrentIndex(0); +} + } // CppTools namespace diff --git a/src/plugins/cpptools/clangdiagnosticconfigswidget.h b/src/plugins/cpptools/clangdiagnosticconfigswidget.h index ff11815a229..40d574b9442 100644 --- a/src/plugins/cpptools/clangdiagnosticconfigswidget.h +++ b/src/plugins/cpptools/clangdiagnosticconfigswidget.h @@ -33,9 +33,17 @@ #include #include +#include + +QT_FORWARD_DECLARE_CLASS(QListWidgetItem) + namespace CppTools { -namespace Ui { class ClangDiagnosticConfigsWidget; } +namespace Ui { +class ClangDiagnosticConfigsWidget; +class ClazyChecks; +class TidyChecks; +} class CPPTOOLS_EXPORT ClangDiagnosticConfigsWidget : public QWidget { @@ -59,15 +67,23 @@ signals: void customConfigsChanged(const CppTools::ClangDiagnosticConfigs &customConfigs); private: + void setupPluginsWidgets(); + void onCurrentConfigChanged(int); void onCopyButtonClicked(); void onRemoveButtonClicked(); + void onClangTidyItemChanged(QListWidgetItem *item); void onDiagnosticOptionsEdited(); void syncWidgetsToModel(const Core::Id &configToSelect = Core::Id()); void syncConfigChooserToModel(const Core::Id &configToSelect = Core::Id()); void syncOtherWidgetsToComboBox(); + void syncClangTidyWidgets(const ClangDiagnosticConfig &config); + void syncClazyWidgets(const ClangDiagnosticConfig &config); + + void setClazyLevelDescription(int index); + void updateConfig(const CppTools::ClangDiagnosticConfig &config); bool isConfigChooserEmpty() const; const ClangDiagnosticConfig ¤tConfig() const; @@ -75,6 +91,9 @@ private: void setDiagnosticOptions(const QString &options); void updateValidityWidgets(const QString &errorMessage); + void connectClangTidyItemChanged(); + void disconnectClangTidyItemChanged(); + void connectConfigChooserCurrentIndex(); void disconnectConfigChooserCurrentIndex(); void connectDiagnosticOptionsChanged(); @@ -84,6 +103,12 @@ private: Ui::ClangDiagnosticConfigsWidget *m_ui; ClangDiagnosticConfigsModel m_diagnosticConfigsModel; QHash m_notAcceptedOptions; + + std::unique_ptr m_clazyChecks; + QWidget *m_clazyChecksWidget = nullptr; + + std::unique_ptr m_tidyChecks; + QWidget *m_tidyChecksWidget = nullptr; }; } // CppTools namespace diff --git a/src/plugins/cpptools/clangdiagnosticconfigswidget.ui b/src/plugins/cpptools/clangdiagnosticconfigswidget.ui index 251868faca1..201a6f67ccf 100644 --- a/src/plugins/cpptools/clangdiagnosticconfigswidget.ui +++ b/src/plugins/cpptools/clangdiagnosticconfigswidget.ui @@ -93,6 +93,9 @@ + + + diff --git a/src/plugins/cpptools/compileroptionsbuilder.cpp b/src/plugins/cpptools/compileroptionsbuilder.cpp index 26a133824ad..9c6c7d18419 100644 --- a/src/plugins/cpptools/compileroptionsbuilder.cpp +++ b/src/plugins/cpptools/compileroptionsbuilder.cpp @@ -27,8 +27,10 @@ #include +#include #include +#include #include #include @@ -37,6 +39,8 @@ namespace CppTools { +static constexpr char SYSTEM_INCLUDE_PREFIX[] = "-isystem"; + CompilerOptionsBuilder::CompilerOptionsBuilder(const ProjectPart &projectPart, const QString &clangVersion, const QString &clangResourceDirectory) @@ -119,10 +123,23 @@ void CompilerOptionsBuilder::enableExceptions() add(QLatin1String("-fexceptions")); } +static Utils::FileName absoluteDirectory(const QString &filePath) +{ + return Utils::FileName::fromString(QFileInfo(filePath + '/').absolutePath()); +} + +static Utils::FileName projectTopLevelDirectory(const ProjectPart &projectPart) +{ + if (!projectPart.project) + return Utils::FileName(); + return projectPart.project->projectDirectory(); +} + void CompilerOptionsBuilder::addHeaderPathOptions() { typedef ProjectPartHeaderPath HeaderPath; const QString defaultPrefix = includeDirOption(); + const Utils::FileName projectDirectory = projectTopLevelDirectory(m_projectPart); QStringList result; @@ -134,6 +151,7 @@ void CompilerOptionsBuilder::addHeaderPathOptions() continue; QString prefix; + Utils::FileName path; switch (headerPath.type) { case HeaderPath::FrameworkPath: prefix = QLatin1String("-F"); @@ -141,7 +159,11 @@ void CompilerOptionsBuilder::addHeaderPathOptions() default: // This shouldn't happen, but let's be nice..: // intentional fall-through: case HeaderPath::IncludePath: - prefix = defaultPrefix; + path = absoluteDirectory(headerPath.path); + if (path == projectDirectory || path.isChildOf(projectDirectory)) + prefix = defaultPrefix; + else + prefix = SYSTEM_INCLUDE_PREFIX; break; } @@ -409,7 +431,7 @@ void CompilerOptionsBuilder::addDefineFunctionMacrosMsvc() QString CompilerOptionsBuilder::includeDirOption() const { - return QLatin1String("-isystem"); + return QLatin1String("-I"); } QByteArray CompilerOptionsBuilder::macroOption(const ProjectExplorer::Macro ¯o) const @@ -506,7 +528,7 @@ void CompilerOptionsBuilder::addPredefinedHeaderPathsOptions() void CompilerOptionsBuilder::addClangIncludeFolder() { QTC_CHECK(!m_clangVersion.isEmpty()); - add(includeDirOption()); + add(SYSTEM_INCLUDE_PREFIX); add(clangIncludeDirectory()); } diff --git a/src/plugins/cpptools/cppcodemodelsettings.cpp b/src/plugins/cpptools/cppcodemodelsettings.cpp index 15ec9c9bfee..cc39f001299 100644 --- a/src/plugins/cpptools/cppcodemodelsettings.cpp +++ b/src/plugins/cpptools/cppcodemodelsettings.cpp @@ -55,6 +55,12 @@ static QString clangDiagnosticConfigsArrayDisplayNameKey() static QString clangDiagnosticConfigsArrayWarningsKey() { return QLatin1String("diagnosticOptions"); } +static QString clangDiagnosticConfigsArrayClangTidyChecksKey() +{ return QLatin1String("clangTidyChecks"); } + +static QString clangDiagnosticConfigsArrayClazyChecksKey() +{ return QLatin1String("clazyChecks"); } + static QString pchUsageKey() { return QLatin1String(Constants::CPPTOOLS_MODEL_MANAGER_PCH_USAGE); } @@ -67,15 +73,12 @@ static QString skipIndexingBigFilesKey() static QString indexerFileSizeLimitKey() { return QLatin1String(Constants::CPPTOOLS_INDEXER_FILE_SIZE_LIMIT); } -static QString tidyChecksKey() -{ return QLatin1String(Constants::CPPTOOLS_TIDY_CHECKS); } - -static QString clazyChecksKey() -{ return QLatin1String(Constants::CPPTOOLS_CLAZY_CHECKS); } - -void CppCodeModelSettings::fromSettings(QSettings *s) +static ClangDiagnosticConfigs customDiagnosticConfigsFromSettings(QSettings *s) { - s->beginGroup(QLatin1String(Constants::CPPTOOLS_SETTINGSGROUP)); + QTC_ASSERT(s->group() == QLatin1String(Constants::CPPTOOLS_SETTINGSGROUP), + return ClangDiagnosticConfigs()); + + ClangDiagnosticConfigs configs; const int size = s->beginReadArray(clangDiagnosticConfigsArrayKey()); for (int i = 0; i < size; ++i) { @@ -84,15 +87,30 @@ void CppCodeModelSettings::fromSettings(QSettings *s) ClangDiagnosticConfig config; config.setId(Core::Id::fromSetting(s->value(clangDiagnosticConfigsArrayIdKey()))); config.setDisplayName(s->value(clangDiagnosticConfigsArrayDisplayNameKey()).toString()); - config.setCommandLineWarnings(s->value(clangDiagnosticConfigsArrayWarningsKey()).toStringList()); - m_clangCustomDiagnosticConfigs.append(config); + config.setClangOptions(s->value(clangDiagnosticConfigsArrayWarningsKey()).toStringList()); + config.setClangTidyChecks(s->value(clangDiagnosticConfigsArrayClangTidyChecksKey()).toString()); + config.setClazyChecks(s->value(clangDiagnosticConfigsArrayClazyChecksKey()).toString()); + configs.append(config); } s->endArray(); - const Core::Id diagnosticConfigId = Core::Id::fromSetting( - s->value(clangDiagnosticConfigKey(), - initialClangDiagnosticConfigId().toSetting())); - setClangDiagnosticConfigId(diagnosticConfigId); + return configs; +} + +static Core::Id clangDiagnosticConfigIdFromSettings(QSettings *s) +{ + QTC_ASSERT(s->group() == QLatin1String(Constants::CPPTOOLS_SETTINGSGROUP), return Core::Id()); + + return Core::Id::fromSetting( + s->value(clangDiagnosticConfigKey(), initialClangDiagnosticConfigId().toSetting())); +} + +void CppCodeModelSettings::fromSettings(QSettings *s) +{ + s->beginGroup(QLatin1String(Constants::CPPTOOLS_SETTINGSGROUP)); + + setClangCustomDiagnosticConfigs(customDiagnosticConfigsFromSettings(s)); + setClangDiagnosticConfigId(clangDiagnosticConfigIdFromSettings(s)); const QVariant pchUsageVariant = s->value(pchUsageKey(), initialPchUsage()); setPCHUsage(static_cast(pchUsageVariant.toInt())); @@ -107,11 +125,6 @@ void CppCodeModelSettings::fromSettings(QSettings *s) const QVariant indexerFileSizeLimit = s->value(indexerFileSizeLimitKey(), 5); setIndexerFileSizeLimitInMb(indexerFileSizeLimit.toInt()); - const QVariant tidyChecks = s->value(tidyChecksKey(), QString()); - setTidyChecks(tidyChecks.toString()); - const QVariant clazyChecks = s->value(clazyChecksKey(), QString()); - setClazyChecks(clazyChecks.toString()); - s->endGroup(); emit changed(); @@ -120,6 +133,8 @@ void CppCodeModelSettings::fromSettings(QSettings *s) void CppCodeModelSettings::toSettings(QSettings *s) { s->beginGroup(QLatin1String(Constants::CPPTOOLS_SETTINGSGROUP)); + const ClangDiagnosticConfigs previousConfigs = customDiagnosticConfigsFromSettings(s); + const Core::Id previousConfigId = clangDiagnosticConfigIdFromSettings(s); s->beginWriteArray(clangDiagnosticConfigsArrayKey()); for (int i = 0, size = m_clangCustomDiagnosticConfigs.size(); i < size; ++i) { @@ -128,7 +143,9 @@ void CppCodeModelSettings::toSettings(QSettings *s) s->setArrayIndex(i); s->setValue(clangDiagnosticConfigsArrayIdKey(), config.id().toSetting()); s->setValue(clangDiagnosticConfigsArrayDisplayNameKey(), config.displayName()); - s->setValue(clangDiagnosticConfigsArrayWarningsKey(), config.commandLineWarnings()); + s->setValue(clangDiagnosticConfigsArrayWarningsKey(), config.clangOptions()); + s->setValue(clangDiagnosticConfigsArrayClangTidyChecksKey(), config.clangTidyChecks()); + s->setValue(clangDiagnosticConfigsArrayClazyChecksKey(), config.clazyChecks()); } s->endArray(); @@ -138,11 +155,18 @@ void CppCodeModelSettings::toSettings(QSettings *s) s->setValue(interpretAmbiguousHeadersAsCHeadersKey(), interpretAmbigiousHeadersAsCHeaders()); s->setValue(skipIndexingBigFilesKey(), skipIndexingBigFiles()); s->setValue(indexerFileSizeLimitKey(), indexerFileSizeLimitInMb()); - s->setValue(tidyChecksKey(), tidyChecks()); - s->setValue(clazyChecksKey(), clazyChecks()); s->endGroup(); + QVector invalidated + = ClangDiagnosticConfigsModel::changedOrRemovedConfigs(previousConfigs, + m_clangCustomDiagnosticConfigs); + + if (previousConfigId != clangDiagnosticConfigId() && !invalidated.contains(previousConfigId)) + invalidated.append(previousConfigId); + + if (!invalidated.isEmpty()) + emit clangDiagnosticConfigsInvalidated(invalidated); emit changed(); } @@ -212,23 +236,3 @@ void CppCodeModelSettings::setIndexerFileSizeLimitInMb(int sizeInMB) { m_indexerFileSizeLimitInMB = sizeInMB; } - -QString CppCodeModelSettings::tidyChecks() const -{ - return m_tidyChecks; -} - -void CppCodeModelSettings::setTidyChecks(QString checks) -{ - m_tidyChecks = checks; -} - -QString CppCodeModelSettings::clazyChecks() const -{ - return m_clazyChecks; -} - -void CppCodeModelSettings::setClazyChecks(QString checks) -{ - m_clazyChecks = checks; -} diff --git a/src/plugins/cpptools/cppcodemodelsettings.h b/src/plugins/cpptools/cppcodemodelsettings.h index 22f5b25c6b2..bc91fbd1b8e 100644 --- a/src/plugins/cpptools/cppcodemodelsettings.h +++ b/src/plugins/cpptools/cppcodemodelsettings.h @@ -72,13 +72,8 @@ public: int indexerFileSizeLimitInMb() const; void setIndexerFileSizeLimitInMb(int sizeInMB); - QString tidyChecks() const; - void setTidyChecks(QString checks); - - QString clazyChecks() const; - void setClazyChecks(QString checks); - signals: + void clangDiagnosticConfigsInvalidated(const QVector &configId); void changed(); private: @@ -88,9 +83,6 @@ private: int m_indexerFileSizeLimitInMB = 5; ClangDiagnosticConfigs m_clangCustomDiagnosticConfigs; Core::Id m_clangDiagnosticConfigId; - - QString m_tidyChecks; - QString m_clazyChecks; }; } // namespace CppTools diff --git a/src/plugins/cpptools/cppcodemodelsettingspage.cpp b/src/plugins/cpptools/cppcodemodelsettingspage.cpp index d7f404fb03b..e6af115aed4 100644 --- a/src/plugins/cpptools/cppcodemodelsettingspage.cpp +++ b/src/plugins/cpptools/cppcodemodelsettingspage.cpp @@ -29,8 +29,6 @@ #include "cppmodelmanager.h" #include "cpptoolsconstants.h" #include "ui_cppcodemodelsettingspage.h" -#include "ui_clazychecks.h" -#include "ui_tidychecks.h" #include #include @@ -86,79 +84,6 @@ void CppCodeModelSettingsWidget::setupClangCodeModelWidgets() diagnosticConfigsModel, m_settings->clangDiagnosticConfigId()); m_ui->clangSettingsGroupBox->layout()->addWidget(m_clangDiagnosticConfigsWidget); - - m_ui->clangPlugins->setEnabled(isClangActive); - setupPluginsWidgets(); -} - -void CppCodeModelSettingsWidget::setupPluginsWidgets() -{ - m_clazyChecks.reset(new CppTools::Ui::ClazyChecks); - m_clazyChecksWidget = new QWidget(); - m_clazyChecks->setupUi(m_clazyChecksWidget); - - m_tidyChecks.reset(new CppTools::Ui::TidyChecks); - m_tidyChecksWidget = new QWidget(); - m_tidyChecks->setupUi(m_tidyChecksWidget); - - m_ui->pluginChecks->addTab(m_tidyChecksWidget, tr("ClangTidy")); - m_ui->pluginChecks->addTab(m_clazyChecksWidget, tr("Clazy")); - m_ui->pluginChecks->setCurrentIndex(0); - - setupTidyChecks(); - setupClazyChecks(); -} - -void CppCodeModelSettingsWidget::setupTidyChecks() -{ - m_currentTidyChecks = m_settings->tidyChecks(); - for (int row = 0; row < m_tidyChecks->checksList->count(); ++row) { - QListWidgetItem *item = m_tidyChecks->checksList->item(row); - item->setFlags(item->flags() | Qt::ItemIsUserCheckable); - if (m_currentTidyChecks.indexOf(item->text()) != -1) - item->setCheckState(Qt::Checked); - else - item->setCheckState(Qt::Unchecked); - } - connect(m_tidyChecks->checksList, &QListWidget::itemChanged, [this](QListWidgetItem *item) { - const QString prefix = item->text(); - item->checkState() == Qt::Checked - ? m_currentTidyChecks.append(',' + prefix) - : m_currentTidyChecks.remove(',' + prefix); - }); -} - -void CppCodeModelSettingsWidget::setupClazyChecks() -{ - // Levels descriptions are taken from https://github.com/KDE/clazy - static const std::array levelDescriptions {{ - QString(), - tr("Very stable checks, 99.99% safe, no false-positives."), - tr("Similar to level0, but sometimes (rarely) there might be\n" - "some false-positives."), - tr("Sometimes has false-positives (20-30%)."), - tr("Not always correct, possibly very noisy, might require\n" - "a knowledgeable developer to review, might have a very big\n" - "rate of false-positives, might have bugs.") - }}; - - m_currentClazyChecks = m_settings->clazyChecks(); - if (!m_currentClazyChecks.isEmpty()) { - m_clazyChecks->clazyLevel->setCurrentText(m_currentClazyChecks); - const unsigned index = static_cast(m_clazyChecks->clazyLevel->currentIndex()); - m_clazyChecks->levelDescription->setText(levelDescriptions[index]); - } - - connect(m_clazyChecks->clazyLevel, - static_cast(&QComboBox::currentIndexChanged), - [this](int index) { - m_clazyChecks->levelDescription->setText(levelDescriptions[static_cast(index)]); - if (index == 0) { - m_currentClazyChecks.clear(); - return; - } - m_currentClazyChecks = m_clazyChecks->clazyLevel->itemText(index); - }); } void CppCodeModelSettingsWidget::setupGeneralWidgets() @@ -192,16 +117,6 @@ bool CppCodeModelSettingsWidget::applyClangCodeModelWidgetsToSettings() const settingsChanged = true; } - if (m_settings->tidyChecks() != m_currentTidyChecks) { - m_settings->setTidyChecks(m_currentTidyChecks); - settingsChanged = true; - } - - if (m_settings->clazyChecks() != m_currentClazyChecks) { - m_settings->setClazyChecks(m_currentClazyChecks); - settingsChanged = true; - } - return settingsChanged; } diff --git a/src/plugins/cpptools/cppcodemodelsettingspage.h b/src/plugins/cpptools/cppcodemodelsettingspage.h index 45728d487a8..7a56ca174b6 100644 --- a/src/plugins/cpptools/cppcodemodelsettingspage.h +++ b/src/plugins/cpptools/cppcodemodelsettingspage.h @@ -32,8 +32,6 @@ #include #include -#include - QT_FORWARD_DECLARE_CLASS(QComboBox) QT_FORWARD_DECLARE_CLASS(QSettings) @@ -41,11 +39,6 @@ namespace CppTools { class ClangDiagnosticConfigsWidget; -namespace Ui { -class ClazyChecks; -class TidyChecks; -} // namespace Ui - namespace Internal { namespace Ui { class CppCodeModelSettingsPage; } @@ -64,9 +57,6 @@ public: private: void setupGeneralWidgets(); void setupClangCodeModelWidgets(); - void setupPluginsWidgets(); - void setupTidyChecks(); - void setupClazyChecks(); bool applyGeneralWidgetsToSettings() const; bool applyClangCodeModelWidgetsToSettings() const; @@ -75,14 +65,6 @@ private: Ui::CppCodeModelSettingsPage *m_ui = nullptr; QPointer m_clangDiagnosticConfigsWidget; QSharedPointer m_settings; - - std::unique_ptr m_clazyChecks; - QWidget *m_clazyChecksWidget = nullptr; - QString m_currentClazyChecks; - - std::unique_ptr m_tidyChecks; - QWidget *m_tidyChecksWidget = nullptr; - QString m_currentTidyChecks; }; class CppCodeModelSettingsPage: public Core::IOptionsPage diff --git a/src/plugins/cpptools/cppcodemodelsettingspage.ui b/src/plugins/cpptools/cppcodemodelsettingspage.ui index 35d4c37a427..61351787f07 100644 --- a/src/plugins/cpptools/cppcodemodelsettingspage.ui +++ b/src/plugins/cpptools/cppcodemodelsettingspage.ui @@ -114,18 +114,6 @@ - - - - Clang Plugins - - - - - - - - diff --git a/src/plugins/cpptools/cpptoolsconstants.h b/src/plugins/cpptools/cpptoolsconstants.h index c8dad1066ba..f4c3538feae 100644 --- a/src/plugins/cpptools/cpptoolsconstants.h +++ b/src/plugins/cpptools/cpptoolsconstants.h @@ -56,8 +56,6 @@ const char CPPTOOLS_INTERPRET_AMBIGIUOUS_HEADERS_AS_C_HEADERS[] = "InterpretAmbiguousHeadersAsCHeaders"; const char CPPTOOLS_SKIP_INDEXING_BIG_FILES[] = "SkipIndexingBigFiles"; const char CPPTOOLS_INDEXER_FILE_SIZE_LIMIT[] = "IndexerFileSizeLimit"; -const char CPPTOOLS_TIDY_CHECKS[] = "TidyChecks"; -const char CPPTOOLS_CLAZY_CHECKS[] = "ClazyChecks"; const char CPP_CLANG_BUILTIN_CONFIG_ID_EVERYTHING_WITH_EXCEPTIONS[] = "Builtin.EverythingWithExceptions"; diff --git a/src/plugins/debugger/debuggeractions.cpp b/src/plugins/debugger/debuggeractions.cpp index e8653737999..ebdc77c9d02 100644 --- a/src/plugins/debugger/debuggeractions.cpp +++ b/src/plugins/debugger/debuggeractions.cpp @@ -530,7 +530,7 @@ DebuggerSettings::DebuggerSettings() insertItem(UseToolTipsInBreakpointsView, item); item = new SavedAction(this); - item->setSettingsKey(debugModeGroup, QLatin1String("UseToolTipsInBreakpointsView")); + item->setSettingsKey(debugModeGroup, QLatin1String("UseToolTipsInStackView")); item->setText(tr("Use Tooltips in Stack View when Debugging")); item->setToolTip(tr("

Checking this will enable tooltips in the stack " "view during debugging.")); diff --git a/src/plugins/debugger/debuggerruncontrol.cpp b/src/plugins/debugger/debuggerruncontrol.cpp index a576377a2cd..741a295af2d 100644 --- a/src/plugins/debugger/debuggerruncontrol.cpp +++ b/src/plugins/debugger/debuggerruncontrol.cpp @@ -365,7 +365,13 @@ void DebuggerRunTool::setBreakOnMain(bool on) void DebuggerRunTool::setUseTerminal(bool on) { - if (on && !d->terminalRunner && m_runParameters.cppEngineType == GdbEngineType) { + // CDB has a built-in console that might be preferred by some. + bool useCdbConsole = m_runParameters.cppEngineType == CdbEngineType + && (m_runParameters.startMode == StartInternal + || m_runParameters.startMode == StartExternal) + && boolSetting(UseCdbConsole); + + if (on && !d->terminalRunner && !useCdbConsole) { d->terminalRunner = new TerminalRunner(this); addStartDependency(d->terminalRunner); } @@ -891,15 +897,6 @@ DebuggerRunTool::DebuggerRunTool(RunControl *runControl, Kit *kit, bool allowTer m_engine = createPdbEngine(); } } - - if (m_runParameters.cppEngineType == CdbEngineType - && !boolSetting(UseCdbConsole) - && m_runParameters.inferior.runMode == ApplicationLauncher::Console - && (m_runParameters.startMode == StartInternal - || m_runParameters.startMode == StartExternal)) { - d->terminalRunner = new TerminalRunner(this); - addStartDependency(d->terminalRunner); - } } DebuggerEngine *DebuggerRunTool::activeEngine() const diff --git a/src/plugins/debugger/lldb/lldbengine.cpp b/src/plugins/debugger/lldb/lldbengine.cpp index 3f945afc159..6e26ff3e6e8 100644 --- a/src/plugins/debugger/lldb/lldbengine.cpp +++ b/src/plugins/debugger/lldb/lldbengine.cpp @@ -292,7 +292,6 @@ void LldbEngine::setupEngine() .arg(bp.id().toString()).arg(bp.state())); } } - notifyEngineSetupOk(); } else { notifyEngineSetupFailed(); } diff --git a/src/plugins/modeleditor/modeleditor_plugin.cpp b/src/plugins/modeleditor/modeleditor_plugin.cpp index acaa8f24dce..7571703cbbd 100644 --- a/src/plugins/modeleditor/modeleditor_plugin.cpp +++ b/src/plugins/modeleditor/modeleditor_plugin.cpp @@ -88,16 +88,9 @@ bool ModelEditorPlugin::initialize(const QStringList &arguments, QString *errorS Q_UNUSED(errorString); d->modelsManager = new ModelsManager(this); - addAutoReleasedObject(d->modelsManager); - d->uiController = new UiController(this); - addAutoReleasedObject(d->uiController); - d->modelFactory = new ModelEditorFactory(d->uiController, this); - addAutoReleasedObject(d->modelFactory); - d->settingsController = new SettingsController(this); - addAutoReleasedObject(d->settingsController); Core::JsExpander::registerQObjectForJs(QLatin1String("Modeling"), new JsExtension(this)); diff --git a/src/plugins/qmakeandroidsupport/androidqmakebuildconfigurationfactory.cpp b/src/plugins/qmakeandroidsupport/androidqmakebuildconfigurationfactory.cpp index a644ce6221c..3ffa785d60f 100644 --- a/src/plugins/qmakeandroidsupport/androidqmakebuildconfigurationfactory.cpp +++ b/src/plugins/qmakeandroidsupport/androidqmakebuildconfigurationfactory.cpp @@ -63,11 +63,9 @@ AndroidQmakeBuildConfiguration::AndroidQmakeBuildConfiguration(Target *target) : QmakeBuildConfiguration(target) { updateCacheAndEmitEnvironmentChanged(); - - auto updateGradle = [this] { AndroidManager::updateGradleProperties(BuildConfiguration::target()); }; - - connect(target->project(), &Project::parsingFinished, this, updateGradle); - connect(this, &AndroidQmakeBuildConfiguration::enabledChanged, this, updateGradle); + connect(target->project(), &Project::parsingFinished, this, [this] { + AndroidManager::updateGradleProperties(BuildConfiguration::target()); + }); } void AndroidQmakeBuildConfiguration::initialize(const BuildInfo *info) diff --git a/src/plugins/qmldesigner/components/componentcore/changestyleaction.cpp b/src/plugins/qmldesigner/components/componentcore/changestyleaction.cpp index a6e746d3f0f..41901e6e9de 100644 --- a/src/plugins/qmldesigner/components/componentcore/changestyleaction.cpp +++ b/src/plugins/qmldesigner/components/componentcore/changestyleaction.cpp @@ -64,6 +64,8 @@ QWidget *ChangeStyleWidgetAction::createWidget(QWidget *parent) QComboBox *comboBox = new QComboBox(parent); comboBox->setToolTip(tr(enabledTooltip)); comboBox->addItem("Default"); + comboBox->addItem("Fusion"); + comboBox->addItem("Imagine"); comboBox->addItem("Material"); comboBox->addItem("Universal"); comboBox->setEditable(true); diff --git a/src/plugins/qmldesigner/components/componentcore/componentcore_constants.h b/src/plugins/qmldesigner/components/componentcore/componentcore_constants.h index 0035b90fad3..028d3a21b4b 100644 --- a/src/plugins/qmldesigner/components/componentcore/componentcore_constants.h +++ b/src/plugins/qmldesigner/components/componentcore/componentcore_constants.h @@ -164,6 +164,8 @@ const int priorityGoIntoComponent = 40; const int priorityGenericToolBar = 50; const int priorityLast = 60; +const char addImagesDisplayString[] = QT_TRANSLATE_NOOP("QmlDesignerAddResources", "Image Files"); + } //ComponentCoreConstants } //QmlDesigner diff --git a/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp b/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp index 629f290026e..db4b726f384 100644 --- a/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp +++ b/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp @@ -178,6 +178,16 @@ void DesignerActionManager::setupContext() m_designerActionManagerView->setupContext(); } +QList DesignerActionManager::addResourceHandler() const +{ + return m_addResourceHandler; +} + +void DesignerActionManager::registerAddResourceHandler(const AddResourceHandler &handler) +{ + m_addResourceHandler.append(handler); +} + class VisiblityModelNodeAction : public ModelNodeContextMenuAction { public: @@ -359,7 +369,7 @@ bool selectionHasSameParentAndInBaseState(const SelectionContext &context) bool isNotInLayout(const SelectionContext &context) { if (selectionNotEmpty(context)) { - const ModelNode &selectedModelNode = context.selectedModelNodes().constFirst(); + const ModelNode selectedModelNode = context.selectedModelNodes().constFirst(); ModelNode parentModelNode; if (selectedModelNode.hasParentProperty()) @@ -983,6 +993,22 @@ void DesignerActionManager::createDefaultDesignerActions() addDesignerAction(new ChangeStyleAction()); } +void DesignerActionManager::createDefaultAddResourceHandler() +{ + registerAddResourceHandler(AddResourceHandler(ComponentCoreConstants::addImagesDisplayString, + "*.png", + ModelNodeOperations::addImageToProject)); + registerAddResourceHandler(AddResourceHandler(ComponentCoreConstants::addImagesDisplayString, + "*.jpg", + ModelNodeOperations::addImageToProject)); + registerAddResourceHandler(AddResourceHandler(ComponentCoreConstants::addImagesDisplayString, + "*.bmp", + ModelNodeOperations::addImageToProject)); + registerAddResourceHandler(AddResourceHandler(ComponentCoreConstants::addImagesDisplayString, + "*.svg", + ModelNodeOperations::addImageToProject)); +} + void DesignerActionManager::addDesignerAction(ActionInterface *newAction) { m_designerActions.append(QSharedPointer(newAction)); diff --git a/src/plugins/qmldesigner/components/componentcore/designeractionmanager.h b/src/plugins/qmldesigner/components/componentcore/designeractionmanager.h index 6cd7d7f2e2e..b4531db8959 100644 --- a/src/plugins/qmldesigner/components/componentcore/designeractionmanager.h +++ b/src/plugins/qmldesigner/components/componentcore/designeractionmanager.h @@ -42,6 +42,25 @@ namespace QmlDesigner { class DesignerActionManagerView; +typedef std::function AddResourceOperation; + +struct AddResourceHandler +{ +public: + AddResourceHandler( const QString &_category, + const QString &_filter, + AddResourceOperation _operation) + : category(_category) + ,filter(_filter) + ,operation(_operation) + { + } + + QString category; + QString filter; + AddResourceOperation operation; +}; + class DesignerActionToolBar : public Utils::StyledBar { public: @@ -64,6 +83,7 @@ public: QList designerActions() const; void createDefaultDesignerActions(); + void createDefaultAddResourceHandler(); DesignerActionManagerView *view(); DesignerActionToolBar *createToolBar(QWidget *parent = 0) const; @@ -76,9 +96,13 @@ public: DesignerActionManager(const DesignerActionManager&) = delete; DesignerActionManager & operator=(const DesignerActionManager&) = delete; + QList addResourceHandler() const; + void registerAddResourceHandler(const AddResourceHandler &handler); + private: QList > m_designerActions; DesignerActionManagerView *m_designerActionManagerView; + QList m_addResourceHandler; }; } //QmlDesigner diff --git a/src/plugins/qmldesigner/components/componentcore/designeractionmanagerview.cpp b/src/plugins/qmldesigner/components/componentcore/designeractionmanagerview.cpp index 1efd79a1cdf..e46987483f4 100644 --- a/src/plugins/qmldesigner/components/componentcore/designeractionmanagerview.cpp +++ b/src/plugins/qmldesigner/components/componentcore/designeractionmanagerview.cpp @@ -53,7 +53,7 @@ void DesignerActionManagerView::modelAboutToBeDetached(Model *model) void DesignerActionManagerView::nodeCreated(const ModelNode &) { - setupContext(); + setupContext(SelectionContext::UpdateMode::Fast); } void DesignerActionManagerView::nodeRemoved(const ModelNode &, const NodeAbstractProperty &, AbstractView::PropertyChangeFlags) @@ -63,17 +63,17 @@ void DesignerActionManagerView::nodeRemoved(const ModelNode &, const NodeAbstrac void DesignerActionManagerView::nodeAboutToBeReparented(const ModelNode &, const NodeAbstractProperty &, const NodeAbstractProperty &, AbstractView::PropertyChangeFlags) { - setupContext(); + setupContext(SelectionContext::UpdateMode::Fast); } void DesignerActionManagerView::nodeReparented(const ModelNode &, const NodeAbstractProperty &, const NodeAbstractProperty &, AbstractView::PropertyChangeFlags) { - setupContext(); + setupContext(SelectionContext::UpdateMode::Fast); } void DesignerActionManagerView::propertiesRemoved(const QList &) { - setupContext(); + setupContext(SelectionContext::UpdateMode::Fast); } void DesignerActionManagerView::rootNodeTypeChanged(const QString &, int, int) @@ -96,7 +96,7 @@ void DesignerActionManagerView::rewriterEndTransaction() void DesignerActionManagerView::currentStateChanged(const ModelNode &) { - setupContext(); + setupContext(SelectionContext::UpdateMode::Fast); } void DesignerActionManagerView::selectedNodesChanged(const QList &selectedNodes, const QList &) @@ -112,7 +112,7 @@ void DesignerActionManagerView::selectedNodesChanged(const QList &sel void DesignerActionManagerView::nodeOrderChanged(const NodeListProperty &, const ModelNode &, int) { - setupContext(); + setupContext(SelectionContext::UpdateMode::Fast); } void DesignerActionManagerView::importsChanged(const QList &, const QList &) @@ -127,21 +127,21 @@ void DesignerActionManagerView::setDesignerActionList(const QList &, AbstractView::PropertyChangeFlags) { - setupContext(); + setupContext(SelectionContext::UpdateMode::Fast); } void DesignerActionManagerView::variantPropertiesChanged(const QList &, AbstractView::PropertyChangeFlags propertyChangeFlag) { if (propertyChangeFlag == AbstractView::PropertiesAdded) - setupContext(); + setupContext(SelectionContext::UpdateMode::Fast); else if (hasSingleSelectedModelNode()) - setupContext(); + setupContext(SelectionContext::UpdateMode::Fast); } void DesignerActionManagerView::bindingPropertiesChanged(const QList &, AbstractView::PropertyChangeFlags propertyChangeFlag) { if (propertyChangeFlag == AbstractView::PropertiesAdded) - setupContext(); + setupContext(SelectionContext::UpdateMode::Fast); } void DesignerActionManagerView::instancePropertyChanged(const QList > &) diff --git a/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp b/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp index 85e67747502..0861597828f 100644 --- a/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp +++ b/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp @@ -56,6 +56,10 @@ #include +#include +#include +#include + #include #include @@ -1020,6 +1024,27 @@ void addTabBarToStackedContainer(const SelectionContext &selectionContext) } } +bool addImageToProject(const QString &fileName, const QString &directory) +{ + const QString targetFile = directory + "/" + QFileInfo(fileName).fileName(); + const bool success = QFile::copy(fileName, targetFile); + + auto document = QmlDesignerPlugin::instance()->currentDesignDocument(); + + QTC_ASSERT(document, return false); + + if (success) { + ProjectExplorer::Node *node = ProjectExplorer::ProjectTree::nodeForFile(document->fileName()); + if (node) { + ProjectExplorer::FolderNode *containingFolder = node->parentFolderNode(); + if (containingFolder) + containingFolder->addFiles(QStringList(targetFile)); + } + } + + return success; +} + } // namespace Mode } //QmlDesigner diff --git a/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.h b/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.h index 39dfef4975a..0aec320316e 100644 --- a/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.h +++ b/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.h @@ -72,7 +72,7 @@ void addItemToStackedContainer(const SelectionContext &selectionContext); void increaseIndexOfStackedContainer(const SelectionContext &selectionContext); void decreaseIndexOfStackedContainer(const SelectionContext &selectionContext); void addTabBarToStackedContainer(const SelectionContext &selectionContext); - +bool addImageToProject(const QString &fileName, const QString &directory); } // namespace ModelNodeOperationso } //QmlDesigner diff --git a/src/plugins/qmldesigner/components/formeditor/formeditorview.cpp b/src/plugins/qmldesigner/components/formeditor/formeditorview.cpp index fad8a6817be..cd192556835 100644 --- a/src/plugins/qmldesigner/components/formeditor/formeditorview.cpp +++ b/src/plugins/qmldesigner/components/formeditor/formeditorview.cpp @@ -397,7 +397,7 @@ void FormEditorView::changeToCustomTool() int handlingRank = 0; AbstractCustomTool *selectedCustomTool = 0; - const ModelNode &selectedModelNode = selectedModelNodes().constFirst(); + const ModelNode selectedModelNode = selectedModelNodes().constFirst(); foreach (AbstractCustomTool *customTool, m_customToolList) { if (customTool->wantHandleItem(selectedModelNode) > handlingRank) { diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp index 81313c43022..2016fd909c1 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp @@ -45,9 +45,11 @@ #include #include +#include #include #include +#include #include #include #include @@ -76,6 +78,7 @@ ItemLibraryWidget::ItemLibraryWidget(QWidget *parent) : m_itemViewQuickWidget(new QQuickWidget), m_resourcesView(new ItemLibraryResourceView(this)), m_importTagsWidget(new QWidget(this)), + m_addResourcesWidget(new QWidget(this)), m_filterFlag(QtBasic) { m_compressionTimer.setInterval(200); @@ -148,7 +151,8 @@ ItemLibraryWidget::ItemLibraryWidget(QWidget *parent) : layout->addWidget(spacer, 1, 0); layout->addWidget(lineEditFrame, 2, 0, 1, 1); layout->addWidget(m_importTagsWidget.data(), 3, 0, 1, 1); - layout->addWidget(m_stackedWidget.data(), 4, 0, 1, 1); + layout->addWidget(m_addResourcesWidget.data(), 4, 0, 1, 1); + layout->addWidget(m_stackedWidget.data(), 5, 0, 1, 1); setSearchFilter(QString()); @@ -164,6 +168,20 @@ ItemLibraryWidget::ItemLibraryWidget(QWidget *parent) : auto *flowLayout = new Utils::FlowLayout(m_importTagsWidget.data()); flowLayout->setMargin(4); + m_addResourcesWidget->setVisible(false); + flowLayout = new Utils::FlowLayout(m_addResourcesWidget.data()); + flowLayout->setMargin(4); + auto button = new QToolButton(m_addResourcesWidget.data()); + auto font = button->font(); + font.setPixelSize(9); + button->setFont(font); + button->setIcon(Utils::Icons::PLUS.icon()); + button->setText(tr("Add New Resources...")); + button->setToolTip(tr("Add new resources to project.")); + button->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); + flowLayout->addWidget(button); + connect(button, &QToolButton::clicked, this, &ItemLibraryWidget::addResources); + // init the first load of the QML UI elements reloadQmlSource(); } @@ -232,12 +250,15 @@ void ItemLibraryWidget::setCurrentIndexOfStackedWidget(int index) if (index == 2) { m_filterLineEdit->setVisible(false); m_importTagsWidget->setVisible(true); + m_addResourcesWidget->setVisible(false); } if (index == 1) { m_filterLineEdit->setVisible(true); m_importTagsWidget->setVisible(false); + m_addResourcesWidget->setVisible(true); } else { m_filterLineEdit->setVisible(true); m_importTagsWidget->setVisible(true); + m_addResourcesWidget->setVisible(false); } m_stackedWidget->setCurrentIndex(index); @@ -279,6 +300,7 @@ void ItemLibraryWidget::setupImportTagWidget() button->setIcon(Utils::Icons::PLUS.icon()); button->setText(import); button->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); + button->setToolTip(tr("Add import %1").arg(import)); connect(button, &QToolButton::clicked, this, [this, import]() { addPossibleImport(import); }); @@ -366,4 +388,47 @@ void ItemLibraryWidget::addPossibleImport(const QString &name) QmlDesignerPlugin::instance()->currentDesignDocument()->updateSubcomponentManager(); } +void ItemLibraryWidget::addResources() +{ + auto document = QmlDesignerPlugin::instance()->currentDesignDocument(); + + QTC_ASSERT(document, return); + + QList handlers = QmlDesignerPlugin::instance()->viewManager().designerActionManager().addResourceHandler(); + QMultiMap map; + for (const AddResourceHandler &handler : handlers) { + map.insert(handler.category, handler.filter); + } + + QStringList filters; + + for (const QString &key : map.uniqueKeys()) { + QString str = key + " ("; + str.append(map.values(key).join(" ")); + str.append(")"); + filters.append(str); + } + + const auto fileNames = QFileDialog::getOpenFileNames(this, + tr("Add Resources"), + document->fileName().parentDir().toString(), + filters.join(";;")); + + if (!fileNames.isEmpty()) { + const auto directory = QFileDialog::getExistingDirectory(this, + tr("Target Direcotry"), + document->fileName().parentDir().toString()); + + for (const QString &fileName : fileNames) { + for (const AddResourceHandler &handler : handlers) { + QString postfix = handler.filter; + postfix.remove(0, 1); + if (fileName.endsWith(postfix)) + if (!handler.operation(fileName, directory)) + Core::AsynchronousMessageBox::warning(tr("Failed to add File"), tr("Could not add %1 to project.").arg(fileName)); + } + } + } +} + } diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.h b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.h index 8ca7467bfee..5e07f508755 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.h +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.h @@ -96,6 +96,7 @@ private: void removeImport(const QString &name); void addImport(const QString &name, const QString &version); void addPossibleImport(const QString &name); + void addResources(); QTimer m_compressionTimer; QSize m_itemIconSize; @@ -111,6 +112,7 @@ private: QScopedPointer m_itemViewQuickWidget; QScopedPointer m_resourcesView; QScopedPointer m_importTagsWidget; + QScopedPointer m_addResourcesWidget; QShortcut *m_qmlSourceUpdateShortcut; diff --git a/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp b/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp index d9f3fa17365..14776d40d60 100644 --- a/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp +++ b/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp @@ -27,6 +27,7 @@ #include "navigatorview.h" #include +#include #include #include #include @@ -207,7 +208,8 @@ QVariant NavigatorTreeModel::data(const QModelIndex &index, int role) const } else if (role == Qt::ToolTipRole) { if (currentQmlObjectNode.hasError()) { QString errorString = currentQmlObjectNode.error(); - if (currentQmlObjectNode.isRootNode()) + if (DesignerSettings::getValue(DesignerSettingsKey::STANDALONE_MODE).toBool() && + currentQmlObjectNode.isRootNode()) errorString.append(QString("\n%1").arg(tr("Changing the setting \"%1\" might solve the issue.").arg( tr("Use QML emulation layer that is built with the selected Qt")))); diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorcontextobject.cpp b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorcontextobject.cpp index 6966bfe187e..1584d882559 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorcontextobject.cpp +++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorcontextobject.cpp @@ -145,7 +145,7 @@ void PropertyEditorContextObject::toogleExportAlias() if (rewriterView->selectedModelNodes().isEmpty()) return; - const ModelNode &selectedNode = rewriterView->selectedModelNodes().constFirst(); + const ModelNode selectedNode = rewriterView->selectedModelNodes().constFirst(); if (QmlObjectNode::isValidQmlObjectNode(selectedNode)) { QmlObjectNode objectNode(selectedNode); @@ -208,6 +208,25 @@ void PropertyEditorContextObject::changeTypeName(const QString &typeName) } +void PropertyEditorContextObject::insertKeyframe(const QString &propertyName) +{ + if (!m_model || !m_model->rewriterView()) + return; + + /* Ideally we should not missuse the rewriterView + * If we add more code here we have to forward the property editor view */ + RewriterView *rewriterView = m_model->rewriterView(); + + if (rewriterView->selectedModelNodes().isEmpty()) + return; + + ModelNode selectedNode = rewriterView->selectedModelNodes().constFirst(); + + rewriterView->emitCustomNotification("INSERT_KEYFRAME", + { selectedNode }, + { propertyName }); +} + int PropertyEditorContextObject::majorVersion() const { return m_majorVersion; @@ -270,6 +289,20 @@ void PropertyEditorContextObject::setMinorVersion(int minorVersion) emit minorVersionChanged(); } +bool PropertyEditorContextObject::hasActiveTimeline() const +{ + return m_setHasActiveTimeline; +} + +void PropertyEditorContextObject::setHasActiveTimeline(bool b) +{ + if (b == m_setHasActiveTimeline) + return; + + m_setHasActiveTimeline = b; + emit hasActiveTimelineChanged(); +} + void PropertyEditorContextObject::insertInQmlContext(QQmlContext *context) { m_qmlContext = context; diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorcontextobject.h b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorcontextobject.h index f087bdaea1e..212f5742cdd 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorcontextobject.h +++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorcontextobject.h @@ -55,6 +55,8 @@ class PropertyEditorContextObject : public QObject Q_PROPERTY(bool hasAliasExport READ hasAliasExport NOTIFY hasAliasExportChanged) + Q_PROPERTY(bool hasActiveTimeline READ hasActiveTimeline NOTIFY hasActiveTimelineChanged) + Q_PROPERTY(QQmlPropertyMap* backendValues READ backendValues WRITE setBackendValues NOTIFY backendValuesChanged) Q_PROPERTY(QQmlComponent* specificQmlComponent READ specificQmlComponent NOTIFY specificQmlComponentChanged) @@ -81,6 +83,7 @@ public: Q_INVOKABLE void toogleExportAlias(); Q_INVOKABLE void changeTypeName(const QString &typeName); + Q_INVOKABLE void insertKeyframe(const QString &propertyName); int majorVersion() const; int majorQtQuickVersion() const; @@ -91,6 +94,9 @@ public: int minorVersion() const; void setMinorVersion(int minorVersion); + bool hasActiveTimeline() const; + void setHasActiveTimeline(bool b); + void insertInQmlContext(QQmlContext *context); QQmlComponent *specificQmlComponent(); @@ -110,6 +116,7 @@ signals: void minorQtQuickVersionChanged(); void specificQmlComponentChanged(); void hasAliasExportChanged(); + void hasActiveTimelineChanged(); public slots: void setGlobalBaseUrl(const QUrl &newBaseUrl); @@ -153,6 +160,8 @@ private: Model *m_model = nullptr; bool m_aliasExport = false; + + bool m_setHasActiveTimeline = false; }; } //QmlDesigner { diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp index 7c6435a1b89..9a0cba3ca08 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp +++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp @@ -29,6 +29,7 @@ #include "propertyeditortransaction.h" #include #include +#include #include #include @@ -328,6 +329,9 @@ void PropertyEditorQmlBackend::setup(const QmlObjectNode &qmlObjectNode, const Q contextObject()->setIsBaseState(qmlObjectNode.isInBaseState()); contextObject()->setHasAliasExport(qmlObjectNode.isAliasExported()); + + contextObject()->setHasActiveTimeline(QmlTimelineMutator::hasActiveTimeline(qmlObjectNode.view())); + contextObject()->setSelectionChanged(false); contextObject()->setSelectionChanged(false); diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.cpp b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.cpp index 63e415f1b96..7ac69fb2ae4 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.cpp +++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.cpp @@ -30,6 +30,7 @@ #include "propertyeditortransaction.h" #include +#include #include #include @@ -368,6 +369,14 @@ bool PropertyEditorView::locked() const return m_locked; } +void PropertyEditorView::nodeCreated(const ModelNode &modelNode) +{ + if (!m_qmlBackEndForCurrentType->contextObject()->hasActiveTimeline() + && QmlTimelineMutator::isValidQmlTimelineMutator(modelNode)) { + m_qmlBackEndForCurrentType->contextObject()->setHasActiveTimeline(QmlTimelineMutator::hasActiveTimeline(this)); + } +} + void PropertyEditorView::updateSize() { if (!m_qmlBackEndForCurrentType) diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.h b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.h index 316164f4c29..0455a0d7f7f 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.h +++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.h @@ -93,6 +93,8 @@ public: bool locked() const; + void nodeCreated(const ModelNode &createdNode); + protected: void timerEvent(QTimerEvent *event) override; void setupPane(const TypeName &typeName); diff --git a/src/plugins/qmldesigner/designercore/include/qmltimelinemutator.h b/src/plugins/qmldesigner/designercore/include/qmltimelinemutator.h index 8cddecba803..0be3cc1d385 100644 --- a/src/plugins/qmldesigner/designercore/include/qmltimelinemutator.h +++ b/src/plugins/qmldesigner/designercore/include/qmltimelinemutator.h @@ -65,6 +65,7 @@ public: QList allTargets() const; QList framesForTarget(const ModelNode &target) const; void destroyFramesForTarget(const ModelNode &target); + static bool hasActiveTimeline(AbstractView *view); private: void addFramesIfNotExists(const ModelNode &node, const PropertyName &propertyName); diff --git a/src/plugins/qmldesigner/designercore/model/qmltimelinemutator.cpp b/src/plugins/qmldesigner/designercore/model/qmltimelinemutator.cpp index 82660513699..319a9a64215 100644 --- a/src/plugins/qmldesigner/designercore/model/qmltimelinemutator.cpp +++ b/src/plugins/qmldesigner/designercore/model/qmltimelinemutator.cpp @@ -210,6 +210,23 @@ void QmlTimelineMutator::destroyFramesForTarget(const ModelNode &target) frames.destroy(); } +bool QmlTimelineMutator::hasActiveTimeline(AbstractView *view) +{ + if (view && view->isAttached()) { + if (!view->model()->hasImport(Import::createLibraryImport("QtQuick.Timeline", "1.0"), true, true)) + return false; + + const ModelNode root = view->rootModelNode(); + if (root.isValid()) + for (const ModelNode &child : root.directSubModelNodes()) { + if (QmlTimelineMutator::isValidQmlTimelineMutator(child)) + return QmlTimelineMutator(child).isEnabled(); + } + } + + return false; +} + void QmlTimelineMutator::addFramesIfNotExists(const ModelNode &node, const PropertyName &propertyName) { if (!isValid()) diff --git a/src/plugins/qmldesigner/designersettings.cpp b/src/plugins/qmldesigner/designersettings.cpp index ec7d1397283..af653636d67 100644 --- a/src/plugins/qmldesigner/designersettings.cpp +++ b/src/plugins/qmldesigner/designersettings.cpp @@ -76,6 +76,7 @@ void DesignerSettings::fromSettings(QSettings *settings) restoreValue(settings, DesignerSettingsKey::IGNORE_DEVICE_PIXEL_RATIO, false); restoreValue(settings, DesignerSettingsKey::STATESEDITOR_EXPANDED, false); restoreValue(settings, DesignerSettingsKey::NAVIGATOR_SHOW_ONLY_VISIBLE_ITEMS, true); + restoreValue(settings, DesignerSettingsKey::STANDALONE_MODE, false); settings->endGroup(); settings->endGroup(); diff --git a/src/plugins/qmldesigner/designersettings.h b/src/plugins/qmldesigner/designersettings.h index 7172c10491e..8a29de676d5 100644 --- a/src/plugins/qmldesigner/designersettings.h +++ b/src/plugins/qmldesigner/designersettings.h @@ -63,6 +63,7 @@ const char STATESEDITOR_EXPANDED[] = "StatesEditorExpanded"; const char NAVIGATOR_SHOW_ONLY_VISIBLE_ITEMS[] = "NavigatorShowOnlyVisibleItems"; const char REFORMAT_UI_QML_FILES[] = "ReformatUiQmlFiles"; /* These settings are not exposed in ui. */ const char IGNORE_DEVICE_PIXEL_RATIO[] = "IgnoreDevicePixelRaio"; /* The settings can be used to turn off the feature, if there are serious issues */ +const char STANDALONE_MODE[] = "StandAloneMode"; } class DesignerSettings : public QHash diff --git a/src/plugins/qmldesigner/designmodewidget.cpp b/src/plugins/qmldesigner/designmodewidget.cpp index 1008a26e3ac..7a48b4b0b6a 100644 --- a/src/plugins/qmldesigner/designmodewidget.cpp +++ b/src/plugins/qmldesigner/designmodewidget.cpp @@ -229,8 +229,10 @@ static void hideToolButtons(QList &buttons) void DesignModeWidget::setup() { - viewManager().designerActionManager().createDefaultDesignerActions(); - viewManager().designerActionManager().polishActions(); + auto &actionManager = viewManager().designerActionManager(); + actionManager.createDefaultDesignerActions(); + actionManager.createDefaultAddResourceHandler(); + actionManager.polishActions(); QList factories = Core::INavigationWidgetFactory::allNavigationFactories(); diff --git a/src/plugins/qmldesigner/qmldesignerextension/connectioneditor/bindingmodel.cpp b/src/plugins/qmldesigner/qmldesignerextension/connectioneditor/bindingmodel.cpp index 88bb7ffec26..9b08e5179c5 100644 --- a/src/plugins/qmldesigner/qmldesignerextension/connectioneditor/bindingmodel.cpp +++ b/src/plugins/qmldesigner/qmldesignerextension/connectioneditor/bindingmodel.cpp @@ -222,7 +222,7 @@ static PropertyName unusedProperty(const ModelNode &modelNode) void BindingModel::addBindingForCurrentNode() { if (connectionView()->selectedModelNodes().count() == 1) { - const ModelNode &modelNode = connectionView()->selectedModelNodes().constFirst(); + const ModelNode modelNode = connectionView()->selectedModelNodes().constFirst(); if (modelNode.isValid()) { try { modelNode.bindingProperty(unusedProperty(modelNode)).setExpression(QLatin1String("none.none")); diff --git a/src/plugins/qmldesigner/qmldesignerextension/connectioneditor/connectionmodel.cpp b/src/plugins/qmldesigner/qmldesignerextension/connectioneditor/connectionmodel.cpp index 2cde52ec617..7c79334ea2c 100644 --- a/src/plugins/qmldesigner/qmldesignerextension/connectioneditor/connectionmodel.cpp +++ b/src/plugins/qmldesigner/qmldesignerextension/connectioneditor/connectionmodel.cpp @@ -271,7 +271,7 @@ void ConnectionModel::addConnection() if (connectionView()->selectedModelNodes().count() == 1 && !connectionView()->selectedModelNodes().constFirst().id().isEmpty()) { - const ModelNode &selectedNode = connectionView()->selectedModelNodes().constFirst(); + const ModelNode selectedNode = connectionView()->selectedModelNodes().constFirst(); newNode.bindingProperty("target").setExpression(selectedNode.id()); } else { newNode.bindingProperty("target").setExpression(QLatin1String("parent")); diff --git a/src/plugins/qmldesigner/qmldesignerextension/connectioneditor/dynamicpropertiesmodel.cpp b/src/plugins/qmldesigner/qmldesignerextension/connectioneditor/dynamicpropertiesmodel.cpp index a6cb2d911bf..620cd9bf0f7 100644 --- a/src/plugins/qmldesigner/qmldesignerextension/connectioneditor/dynamicpropertiesmodel.cpp +++ b/src/plugins/qmldesigner/qmldesignerextension/connectioneditor/dynamicpropertiesmodel.cpp @@ -265,7 +265,7 @@ QStringList DynamicPropertiesModel::possibleTargetProperties(const BindingProper void DynamicPropertiesModel::addDynamicPropertyForCurrentNode() { if (connectionView()->selectedModelNodes().count() == 1) { - const ModelNode &modelNode = connectionView()->selectedModelNodes().constFirst(); + const ModelNode modelNode = connectionView()->selectedModelNodes().constFirst(); if (modelNode.isValid()) { try { modelNode.variantProperty(unusedProperty(modelNode)).setDynamicTypeNameAndValue("string", QLatin1String("none.none")); diff --git a/src/plugins/qmldesigner/settingspage.cpp b/src/plugins/qmldesigner/settingspage.cpp index 0a32af56eac..6d904a49c22 100644 --- a/src/plugins/qmldesigner/settingspage.cpp +++ b/src/plugins/qmldesigner/settingspage.cpp @@ -210,6 +210,11 @@ void SettingsPageWidget::setSettings(const DesignerSettings &settings) DesignerSettingsKey::ENABLE_MODEL_EXCEPTION_OUTPUT).toBool()); m_ui.controls2StyleComboBox->setCurrentText(m_ui.styleLineEdit->text()); + + if (settings.value(DesignerSettingsKey::STANDALONE_MODE).toBool()) { + m_ui.emulationGroupBox->hide(); + m_ui.debugGroupBox->hide(); + } } SettingsPage::SettingsPage() : diff --git a/src/plugins/qmldesigner/settingspage.ui b/src/plugins/qmldesigner/settingspage.ui index ca00b6fc411..afa70d87787 100644 --- a/src/plugins/qmldesigner/settingspage.ui +++ b/src/plugins/qmldesigner/settingspage.ui @@ -216,7 +216,7 @@ - + QML Emulation Layer @@ -411,7 +411,7 @@ - + Debugging diff --git a/src/plugins/qmlprofiler/qmlprofilerstatisticsview.cpp b/src/plugins/qmlprofiler/qmlprofilerstatisticsview.cpp index b603def7ba7..e415ec2f19e 100644 --- a/src/plugins/qmlprofiler/qmlprofilerstatisticsview.cpp +++ b/src/plugins/qmlprofiler/qmlprofilerstatisticsview.cpp @@ -107,41 +107,39 @@ static void setViewDefaults(Utils::TreeView *view) static QString displayHeader(Fields header) { - static const char ctxt[] = "QmlProfiler::Internal::QmlProfilerEventsMainView"; - switch (header) { case Callee: - return QCoreApplication::translate(ctxt, "Callee"); + return QmlProfilerStatisticsMainView::tr("Callee"); case CalleeDescription: - return QCoreApplication::translate(ctxt, "Callee Description"); + return QmlProfilerStatisticsMainView::tr("Callee Description"); case Caller: - return QCoreApplication::translate(ctxt, "Caller"); + return QmlProfilerStatisticsMainView::tr("Caller"); case CallerDescription: - return QCoreApplication::translate(ctxt, "Caller Description"); + return QmlProfilerStatisticsMainView::tr("Caller Description"); case CallCount: - return QCoreApplication::translate(ctxt, "Calls"); + return QmlProfilerStatisticsMainView::tr("Calls"); case Details: - return QCoreApplication::translate(ctxt, "Details"); + return QmlProfilerStatisticsMainView::tr("Details"); case Location: - return QCoreApplication::translate(ctxt, "Location"); + return QmlProfilerStatisticsMainView::tr("Location"); case MaxTime: - return QCoreApplication::translate(ctxt, "Longest Time"); + return QmlProfilerStatisticsMainView::tr("Longest Time"); case TimePerCall: - return QCoreApplication::translate(ctxt, "Mean Time"); + return QmlProfilerStatisticsMainView::tr("Mean Time"); case SelfTime: - return QCoreApplication::translate(ctxt, "Self Time"); + return QmlProfilerStatisticsMainView::tr("Self Time"); case SelfTimeInPercent: - return QCoreApplication::translate(ctxt, "Self Time in Percent"); + return QmlProfilerStatisticsMainView::tr("Self Time in Percent"); case MinTime: - return QCoreApplication::translate(ctxt, "Shortest Time"); + return QmlProfilerStatisticsMainView::tr("Shortest Time"); case TimeInPercent: - return QCoreApplication::translate(ctxt, "Time in Percent"); + return QmlProfilerStatisticsMainView::tr("Time in Percent"); case TotalTime: - return QCoreApplication::translate(ctxt, "Total Time"); + return QmlProfilerStatisticsMainView::tr("Total Time"); case Type: - return QCoreApplication::translate(ctxt, "Type"); + return QmlProfilerStatisticsMainView::tr("Type"); case MedianTime: - return QCoreApplication::translate(ctxt, "Median Time"); + return QmlProfilerStatisticsMainView::tr("Median Time"); default: return QString(); } diff --git a/src/plugins/texteditor/texteditor.cpp b/src/plugins/texteditor/texteditor.cpp index a0cbd176999..32183afc2f7 100644 --- a/src/plugins/texteditor/texteditor.cpp +++ b/src/plugins/texteditor/texteditor.cpp @@ -7934,10 +7934,13 @@ void BaseTextEditor::setContextHelpId(const QString &id) void TextEditorWidget::contextHelpId(const IContext::HelpIdCallback &callback) { - if (d->m_contextHelpId.isEmpty() && !d->m_hoverHandlers.isEmpty()) - d->m_hoverHandlers.first()->contextHelpId(this, textCursor().position(), callback); - else + if (d->m_contextHelpId.isEmpty() && !d->m_hoverHandlers.isEmpty()) { + d->m_hoverHandlers.first()->contextHelpId(this, + Text::wordStartCursor(textCursor()).position(), + callback); + } else { callback(d->m_contextHelpId); + } } void TextEditorWidget::setContextHelpId(const QString &id) diff --git a/src/shared/qbs b/src/shared/qbs index 6655d563c3c..8355ba92901 160000 --- a/src/shared/qbs +++ b/src/shared/qbs @@ -1 +1 @@ -Subproject commit 6655d563c3cac6dbfd61bfb3dd15ae5b9467d5ae +Subproject commit 8355ba92901715bc9366c9a0218fa756ae457408 diff --git a/src/tools/clangbackend/source/clangfollowsymbol.cpp b/src/tools/clangbackend/source/clangfollowsymbol.cpp index 26de30ed347..2d8b7004ebe 100644 --- a/src/tools/clangbackend/source/clangfollowsymbol.cpp +++ b/src/tools/clangbackend/source/clangfollowsymbol.cpp @@ -107,7 +107,7 @@ static SourceRange getOperatorRange(const CXTranslationUnit tu, ++operatorIndex; } const CXSourceLocation end = clang_getTokenLocation(tu, tokens.data[operatorIndex]); - return SourceRange(clang_getRange(start, end)); + return SourceRange(tu, clang_getRange(start, end)); } static SourceRangeContainer extractMatchingTokenRange(const Cursor &cursor, @@ -128,7 +128,7 @@ static SourceRangeContainer extractMatchingTokenRange(const Cursor &cursor, continue; } } - return SourceRange(clang_getTokenExtent(tu, tokens.data[i])); + return SourceRange(tu, clang_getTokenExtent(tu, tokens.data[i])); } return SourceRangeContainer(); } @@ -137,7 +137,7 @@ static int getTokenIndex(CXTranslationUnit tu, const Tokens &tokens, uint line, { int tokenIndex = -1; for (int i = static_cast(tokens.tokenCount - 1); i >= 0; --i) { - const SourceRange range = clang_getTokenExtent(tu, tokens.data[i]); + const SourceRange range(tu, clang_getTokenExtent(tu, tokens.data[i])); if (range.contains(line, column)) { tokenIndex = i; break; diff --git a/src/tools/clangbackend/source/clangreferencescollector.cpp b/src/tools/clangbackend/source/clangreferencescollector.cpp index 64d9b61392b..ff8465c53f4 100644 --- a/src/tools/clangbackend/source/clangreferencescollector.cpp +++ b/src/tools/clangbackend/source/clangreferencescollector.cpp @@ -155,7 +155,7 @@ ReferencesCollector::~ReferencesCollector() bool ReferencesCollector::isWithinTokenRange(CXToken token, uint line, uint column) const { - const SourceRange range = clang_getTokenExtent(m_cxTranslationUnit, token); + const SourceRange range {m_cxTranslationUnit, clang_getTokenExtent(m_cxTranslationUnit, token)}; return range.contains(line, column); } @@ -229,7 +229,8 @@ ReferencesResult ReferencesCollector::collect(uint line, uint column, bool local const Utf8String identifier = ClangString(clang_getTokenSpelling(m_cxTranslationUnit, token)); for (uint i = 0; i < m_cxTokenCount; ++i) { if (checkToken(i, identifier, usr)) { - const SourceRange range = clang_getTokenExtent(m_cxTranslationUnit, m_cxTokens[i]); + const SourceRange range {m_cxTranslationUnit, + clang_getTokenExtent(m_cxTranslationUnit, m_cxTokens[i])}; result.references.append(range); } } diff --git a/src/tools/clangbackend/source/clangtranslationunit.cpp b/src/tools/clangbackend/source/clangtranslationunit.cpp index da06999b614..cce7548b3c2 100644 --- a/src/tools/clangbackend/source/clangtranslationunit.cpp +++ b/src/tools/clangbackend/source/clangtranslationunit.cpp @@ -161,7 +161,7 @@ ReferencesResult TranslationUnit::references(uint line, uint column, bool localR DiagnosticSet TranslationUnit::diagnostics() const { - return DiagnosticSet(clang_getDiagnosticSetFromTU(m_cxTranslationUnit)); + return DiagnosticSet(m_cxTranslationUnit, clang_getDiagnosticSetFromTU(m_cxTranslationUnit)); } SourceLocation TranslationUnit::sourceLocationAt(uint line,uint column) const diff --git a/src/tools/clangbackend/source/cursor.cpp b/src/tools/clangbackend/source/cursor.cpp index 41a0465e7a0..8b9b22f7cc5 100644 --- a/src/tools/clangbackend/source/cursor.cpp +++ b/src/tools/clangbackend/source/cursor.cpp @@ -283,7 +283,7 @@ CXFile Cursor::includedFile() const SourceLocation Cursor::sourceLocation() const { - return clang_getCursorLocation(cxCursor); + return {cxTranslationUnit(), clang_getCursorLocation(cxCursor)}; } CXSourceLocation Cursor::cxSourceLocation() const @@ -293,7 +293,7 @@ CXSourceLocation Cursor::cxSourceLocation() const SourceRange Cursor::sourceRange() const { - return clang_getCursorExtent(cxCursor); + return {cxTranslationUnit(), clang_getCursorExtent(cxCursor)}; } CXSourceRange Cursor::cxSourceRange() const @@ -308,7 +308,7 @@ CXTranslationUnit Cursor::cxTranslationUnit() const SourceRange Cursor::commentRange() const { - return clang_Cursor_getCommentRange(cxCursor); + return {cxTranslationUnit(), clang_Cursor_getCommentRange(cxCursor)}; } bool Cursor::hasSameSourceLocationAs(const Cursor &other) const diff --git a/src/tools/clangbackend/source/diagnostic.cpp b/src/tools/clangbackend/source/diagnostic.cpp index 5e74970ac24..b7bcf5b02f6 100644 --- a/src/tools/clangbackend/source/diagnostic.cpp +++ b/src/tools/clangbackend/source/diagnostic.cpp @@ -36,8 +36,9 @@ namespace ClangBackEnd { -Diagnostic::Diagnostic(CXDiagnostic cxDiagnostic) - : cxDiagnostic(cxDiagnostic) +Diagnostic::Diagnostic(CXTranslationUnit translationUnit, CXDiagnostic cxDiagnostic) + : cxDiagnostic(cxDiagnostic), + cxTranslationUnit(translationUnit) { } @@ -47,9 +48,11 @@ Diagnostic::~Diagnostic() } Diagnostic::Diagnostic(Diagnostic &&other) - : cxDiagnostic(std::move(other.cxDiagnostic)) + : cxDiagnostic(std::move(other.cxDiagnostic)), + cxTranslationUnit(std::move(other.cxTranslationUnit)) { other.cxDiagnostic = nullptr; + other.cxTranslationUnit = nullptr; } Diagnostic &Diagnostic::operator=(Diagnostic &&other) @@ -57,7 +60,9 @@ Diagnostic &Diagnostic::operator=(Diagnostic &&other) if (this != &other) { clang_disposeDiagnostic(cxDiagnostic); cxDiagnostic = std::move(other.cxDiagnostic); + cxTranslationUnit = std::move(other.cxTranslationUnit); other.cxDiagnostic = nullptr; + other.cxTranslationUnit = nullptr; } return *this; @@ -90,7 +95,7 @@ std::pair Diagnostic::options() const SourceLocation Diagnostic::location() const { - return SourceLocation(clang_getDiagnosticLocation(cxDiagnostic)); + return {cxTranslationUnit, clang_getDiagnosticLocation(cxDiagnostic)}; } DiagnosticSeverity Diagnostic::severity() const @@ -105,7 +110,8 @@ std::vector Diagnostic::ranges() const ranges.reserve(rangesCount); for (uint index = 0; index < rangesCount; ++index) { - const SourceRange sourceRange(clang_getDiagnosticRange(cxDiagnostic, index)); + const SourceRange sourceRange {cxTranslationUnit, + clang_getDiagnosticRange(cxDiagnostic, index)}; if (sourceRange.isValid()) ranges.push_back(std::move(sourceRange)); @@ -123,14 +129,14 @@ std::vector Diagnostic::fixIts() const fixIts.reserve(fixItsCount); for (uint index = 0; index < fixItsCount; ++index) - fixIts.push_back(FixIt(cxDiagnostic, index)); + fixIts.push_back(FixIt(cxTranslationUnit, cxDiagnostic, index)); return fixIts; } DiagnosticSet Diagnostic::childDiagnostics() const { - return DiagnosticSet(clang_getChildDiagnostics(cxDiagnostic)); + return DiagnosticSet(cxTranslationUnit, clang_getChildDiagnostics(cxDiagnostic)); } DiagnosticContainer Diagnostic::toDiagnosticContainer() const diff --git a/src/tools/clangbackend/source/diagnostic.h b/src/tools/clangbackend/source/diagnostic.h index 140322931fb..49161fe40e1 100644 --- a/src/tools/clangbackend/source/diagnostic.h +++ b/src/tools/clangbackend/source/diagnostic.h @@ -73,12 +73,13 @@ public: DiagnosticContainer toDiagnosticContainer() const; private: - Diagnostic(CXDiagnostic cxDiagnostic); + Diagnostic(CXTranslationUnit translationUnit, CXDiagnostic cxDiagnostic); QVector getSourceRangeContainers() const; QVector getFixItContainers() const; private: CXDiagnostic cxDiagnostic; + CXTranslationUnit cxTranslationUnit; }; inline bool operator==(Diagnostic first, Diagnostic second) diff --git a/src/tools/clangbackend/source/diagnosticset.cpp b/src/tools/clangbackend/source/diagnosticset.cpp index ce3504a114a..39c82551371 100644 --- a/src/tools/clangbackend/source/diagnosticset.cpp +++ b/src/tools/clangbackend/source/diagnosticset.cpp @@ -33,8 +33,9 @@ namespace ClangBackEnd { -DiagnosticSet::DiagnosticSet(CXDiagnosticSet cxDiagnosticSet) - : cxDiagnosticSet(cxDiagnosticSet) +DiagnosticSet::DiagnosticSet(CXTranslationUnit translationUnit, CXDiagnosticSet cxDiagnosticSet) + : cxDiagnosticSet(cxDiagnosticSet), + cxTranslationUnit(translationUnit) { } @@ -44,7 +45,8 @@ DiagnosticSet::~DiagnosticSet() } DiagnosticSet::DiagnosticSet(DiagnosticSet &&other) - : cxDiagnosticSet(std::move(other.cxDiagnosticSet)) + : cxDiagnosticSet(std::move(other.cxDiagnosticSet)), + cxTranslationUnit(std::move(other.cxTranslationUnit)) { other.cxDiagnosticSet = nullptr; } @@ -54,7 +56,9 @@ DiagnosticSet &DiagnosticSet::operator=(DiagnosticSet &&other) if (this != &other) { clang_disposeDiagnosticSet(cxDiagnosticSet); cxDiagnosticSet = std::move(other.cxDiagnosticSet); + cxTranslationUnit = std::move(other.cxTranslationUnit); other.cxDiagnosticSet = nullptr; + other.cxTranslationUnit = nullptr; } return *this; @@ -62,22 +66,22 @@ DiagnosticSet &DiagnosticSet::operator=(DiagnosticSet &&other) Diagnostic DiagnosticSet::front() const { - return Diagnostic(clang_getDiagnosticInSet(cxDiagnosticSet, 0)); + return Diagnostic(cxTranslationUnit, clang_getDiagnosticInSet(cxDiagnosticSet, 0)); } Diagnostic DiagnosticSet::back() const { - return Diagnostic(clang_getDiagnosticInSet(cxDiagnosticSet, size() - 1)); + return Diagnostic(cxTranslationUnit, clang_getDiagnosticInSet(cxDiagnosticSet, size() - 1)); } DiagnosticSet::ConstIterator DiagnosticSet::begin() const { - return DiagnosticSetIterator(cxDiagnosticSet, 0); + return DiagnosticSetIterator(cxTranslationUnit, cxDiagnosticSet, 0); } DiagnosticSet::ConstIterator DiagnosticSet::end() const { - return DiagnosticSetIterator(cxDiagnosticSet, size()); + return DiagnosticSetIterator(cxTranslationUnit, cxDiagnosticSet, size()); } QVector DiagnosticSet::toDiagnosticContainers() const @@ -113,7 +117,7 @@ bool DiagnosticSet::isNull() const Diagnostic DiagnosticSet::at(uint index) const { - return Diagnostic(clang_getDiagnosticInSet(cxDiagnosticSet, index)); + return Diagnostic(cxTranslationUnit, clang_getDiagnosticInSet(cxDiagnosticSet, index)); } } // namespace ClangBackEnd diff --git a/src/tools/clangbackend/source/diagnosticset.h b/src/tools/clangbackend/source/diagnosticset.h index e715ad2627b..63f672de419 100644 --- a/src/tools/clangbackend/source/diagnosticset.h +++ b/src/tools/clangbackend/source/diagnosticset.h @@ -72,10 +72,11 @@ public: const IsAcceptedDiagnostic &isAcceptedDiagnostic) const; private: - DiagnosticSet(CXDiagnosticSet cxDiagnosticSet); + DiagnosticSet(CXTranslationUnit translationUnit, CXDiagnosticSet cxDiagnosticSet); private: CXDiagnosticSet cxDiagnosticSet; + CXTranslationUnit cxTranslationUnit; }; } // namespace ClangBackEnd diff --git a/src/tools/clangbackend/source/diagnosticsetiterator.h b/src/tools/clangbackend/source/diagnosticsetiterator.h index 7739dfd3654..72a98319550 100644 --- a/src/tools/clangbackend/source/diagnosticsetiterator.h +++ b/src/tools/clangbackend/source/diagnosticsetiterator.h @@ -25,6 +25,8 @@ #pragma once +#include "diagnostic.h" + #include #include @@ -34,13 +36,15 @@ namespace ClangBackEnd { using uint = unsigned int; class DiagnosticSet; -class Diagnostic; class DiagnosticSetIterator : public std::iterator { public: - DiagnosticSetIterator(CXDiagnosticSet cxDiagnosticSet, uint index) + DiagnosticSetIterator(CXTranslationUnit translationUnit, + CXDiagnosticSet cxDiagnosticSet, + uint index) : cxDiagnosticSet(cxDiagnosticSet), + cxTranslationUnit(translationUnit), index(index) {} @@ -58,7 +62,7 @@ public: DiagnosticSetIterator operator++(int) { uint oldIndex = index++; - return DiagnosticSetIterator(cxDiagnosticSet, oldIndex); + return DiagnosticSetIterator(cxTranslationUnit, cxDiagnosticSet, oldIndex); } bool operator==(const DiagnosticSetIterator &other) @@ -73,11 +77,12 @@ public: Diagnostic operator*() { - return Diagnostic(clang_getDiagnosticInSet(cxDiagnosticSet, index)); + return Diagnostic(cxTranslationUnit, clang_getDiagnosticInSet(cxDiagnosticSet, index)); } private: CXDiagnosticSet cxDiagnosticSet; + CXTranslationUnit cxTranslationUnit; uint index; }; diff --git a/src/tools/clangbackend/source/fixit.cpp b/src/tools/clangbackend/source/fixit.cpp index c2de39c9224..8626602d456 100644 --- a/src/tools/clangbackend/source/fixit.cpp +++ b/src/tools/clangbackend/source/fixit.cpp @@ -46,12 +46,12 @@ FixItContainer FixIt::toFixItContainer() const return FixItContainer(text_, sourceRange.toSourceRangeContainer()); } -FixIt::FixIt(CXDiagnostic cxDiagnostic, uint index) +FixIt::FixIt(CXTranslationUnit translationUnit, CXDiagnostic cxDiagnostic, uint index) { CXSourceRange cxSourceRange; text_ = ClangString(clang_getDiagnosticFixIt(cxDiagnostic, index, &cxSourceRange)); - sourceRange = SourceRange(cxSourceRange); + sourceRange = SourceRange(translationUnit, cxSourceRange); } } // namespace ClangBackEnd diff --git a/src/tools/clangbackend/source/fixit.h b/src/tools/clangbackend/source/fixit.h index f866bc8c18c..b0c1f139aee 100644 --- a/src/tools/clangbackend/source/fixit.h +++ b/src/tools/clangbackend/source/fixit.h @@ -47,7 +47,7 @@ public: FixItContainer toFixItContainer() const; private: - FixIt(CXDiagnostic cxDiagnostic, uint index); + FixIt(CXTranslationUnit translationUnit, CXDiagnostic cxDiagnostic, uint index); private: SourceRange sourceRange; diff --git a/src/tools/clangbackend/source/skippedsourceranges.cpp b/src/tools/clangbackend/source/skippedsourceranges.cpp index ca38510cf2c..f15bd446682 100644 --- a/src/tools/clangbackend/source/skippedsourceranges.cpp +++ b/src/tools/clangbackend/source/skippedsourceranges.cpp @@ -79,7 +79,7 @@ std::vector SkippedSourceRanges::sourceRanges() const sourceRanges.reserve(sourceRangeCount); for (uint i = 0; i < cxSkippedSourceRanges->count; ++i) { - const SourceRange range = cxSkippedSourceRanges->ranges[i]; + const SourceRange range {cxTranslationUnit, cxSkippedSourceRanges->ranges[i]}; const SourceRange adaptedRange = adaptedSourceRange(cxTranslationUnit, range); sourceRanges.push_back(adaptedRange); diff --git a/src/tools/clangbackend/source/sourcelocation.cpp b/src/tools/clangbackend/source/sourcelocation.cpp index 161ed5b0a50..41f68a9ae6f 100644 --- a/src/tools/clangbackend/source/sourcelocation.cpp +++ b/src/tools/clangbackend/source/sourcelocation.cpp @@ -29,10 +29,13 @@ #include "clangfilepath.h" #include "clangstring.h" -#include +#include + +#include + +#include #include -#include namespace ClangBackEnd { @@ -72,8 +75,10 @@ SourceLocationContainer SourceLocation::toSourceLocationContainer() const return SourceLocationContainer(filePath(), line_, column_); } -SourceLocation::SourceLocation(CXSourceLocation cxSourceLocation) +SourceLocation::SourceLocation(CXTranslationUnit cxTranslationUnit, + CXSourceLocation cxSourceLocation) : cxSourceLocation(cxSourceLocation) + , cxTranslationUnit(cxTranslationUnit) { CXFile cxFile; @@ -83,8 +88,22 @@ SourceLocation::SourceLocation(CXSourceLocation cxSourceLocation) &column_, &offset_); - filePath_ = ClangString(clang_getFileName(cxFile)); isFilePathNormalized_ = false; + if (!cxFile) + return; + + filePath_ = ClangString(clang_getFileName(cxFile)); +// CLANG-UPGRADE-CHECK: Remove HAS_GETFILECONTENTS_BACKPORTED check once we require clang >= 7.0 +#if defined(CINDEX_VERSION_HAS_GETFILECONTENTS_BACKPORTED) || CINDEX_VERSION_MINOR >= 47 + if (column_ > 1) { + const uint lineStart = offset_ + 1 - column_; + const char *contents = clang_getFileContents(cxTranslationUnit, cxFile, nullptr); + if (!contents) + return; + column_ = static_cast(QString::fromUtf8(&contents[lineStart], + static_cast(column_)).size()); + } +#endif } SourceLocation::SourceLocation(CXTranslationUnit cxTranslationUnit, @@ -96,6 +115,7 @@ SourceLocation::SourceLocation(CXTranslationUnit cxTranslationUnit, filePath.constData()), line, column)), + cxTranslationUnit(cxTranslationUnit), filePath_(filePath), line_(line), column_(column), diff --git a/src/tools/clangbackend/source/sourcelocation.h b/src/tools/clangbackend/source/sourcelocation.h index 65c3ec69ad6..bf8962161f0 100644 --- a/src/tools/clangbackend/source/sourcelocation.h +++ b/src/tools/clangbackend/source/sourcelocation.h @@ -57,12 +57,14 @@ public: SourceLocationContainer toSourceLocationContainer() const; private: - SourceLocation(CXSourceLocation cxSourceLocation); + SourceLocation(CXTranslationUnit cxTranslationUnit, + CXSourceLocation cxSourceLocation); operator CXSourceLocation() const; private: CXSourceLocation cxSourceLocation; + CXTranslationUnit cxTranslationUnit; mutable Utf8String filePath_; uint line_ = 0; uint column_ = 0; diff --git a/src/tools/clangbackend/source/sourcerange.cpp b/src/tools/clangbackend/source/sourcerange.cpp index 20c6efb5e65..ff1a4753918 100644 --- a/src/tools/clangbackend/source/sourcerange.cpp +++ b/src/tools/clangbackend/source/sourcerange.cpp @@ -39,7 +39,8 @@ SourceRange::SourceRange() } SourceRange::SourceRange(const SourceLocation &start, const SourceLocation &end) - : cxSourceRange(clang_getRange(start, end)) + : cxSourceRange(clang_getRange(start, end)), + cxTranslationUnit(start.cxTranslationUnit) { } @@ -55,12 +56,12 @@ bool SourceRange::isValid() const SourceLocation SourceRange::start() const { - return SourceLocation(clang_getRangeStart(cxSourceRange)); + return {cxTranslationUnit, clang_getRangeStart(cxSourceRange)}; } SourceLocation SourceRange::end() const { - return SourceLocation(clang_getRangeEnd(cxSourceRange)); + return {cxTranslationUnit, clang_getRangeEnd(cxSourceRange)}; } bool SourceRange::contains(unsigned line, unsigned column) const @@ -90,8 +91,9 @@ ClangBackEnd::SourceRange::operator CXSourceRange() const return cxSourceRange; } -SourceRange::SourceRange(CXSourceRange cxSourceRange) - : cxSourceRange(cxSourceRange) +SourceRange::SourceRange(CXTranslationUnit translationUnit, CXSourceRange cxSourceRange) + : cxSourceRange(cxSourceRange), + cxTranslationUnit(translationUnit) { } diff --git a/src/tools/clangbackend/source/sourcerange.h b/src/tools/clangbackend/source/sourcerange.h index b8083e86955..4c30ad43f8e 100644 --- a/src/tools/clangbackend/source/sourcerange.h +++ b/src/tools/clangbackend/source/sourcerange.h @@ -40,7 +40,7 @@ class SourceRange public: SourceRange(); - SourceRange(CXSourceRange cxSourceRange); + SourceRange(CXTranslationUnit cxTranslationUnit, CXSourceRange cxSourceRange); SourceRange(const SourceLocation &start, const SourceLocation &end); bool isNull() const; @@ -58,6 +58,7 @@ public: private: CXSourceRange cxSourceRange; + CXTranslationUnit cxTranslationUnit = nullptr; }; bool operator==(const SourceRange &first, const SourceRange &second); diff --git a/src/tools/clangbackend/source/tokeninfo.cpp b/src/tools/clangbackend/source/tokeninfo.cpp index 703b0f78085..a9c84312861 100644 --- a/src/tools/clangbackend/source/tokeninfo.cpp +++ b/src/tools/clangbackend/source/tokeninfo.cpp @@ -43,7 +43,8 @@ TokenInfo::TokenInfo(const CXCursor &cxCursor, : m_currentOutputArgumentRanges(¤tOutputArgumentRanges), m_originalCursor(cxCursor) { - const SourceRange sourceRange = clang_getTokenExtent(cxTranslationUnit, *cxToken); + const SourceRange sourceRange {cxTranslationUnit, + clang_getTokenExtent(cxTranslationUnit, *cxToken)}; const auto start = sourceRange.start(); const auto end = sourceRange.end(); diff --git a/tests/auto/debugger/tst_dumpers.cpp b/tests/auto/debugger/tst_dumpers.cpp index 743197ff090..2009eb5ab80 100644 --- a/tests/auto/debugger/tst_dumpers.cpp +++ b/tests/auto/debugger/tst_dumpers.cpp @@ -480,19 +480,26 @@ struct DumperOptions QString options; }; +struct Watcher : DumperOptions +{ + Watcher(const QString &iname, const QString &exp) + : DumperOptions(QString("\"watchers\":[{\"exp\":\"%2\",\"iname\":\"%1\"}]").arg(iname, toHex(exp))) + {} +}; + struct Check { Check() {} - Check(const QString &iname, const Value &value, const Type &type) - : iname(iname), expectedName(nameFromIName(iname)), - expectedValue(value), expectedType(type) + Check(const QString &iname, const Name &name, const Value &value, const Type &type) + : iname(iname.startsWith("watch") ? iname : "local." + iname), + expectedName(name), + expectedValue(value), + expectedType(type) {} - Check(const QString &iname, const Name &name, - const Value &value, const Type &type) - : iname(iname), expectedName(name), - expectedValue(value), expectedType(type) + Check(const QString &iname, const Value &value, const Type &type) + : Check(iname, nameFromIName(iname), value, type) {} bool matches(DebuggerEngine engine, int debuggerVersion, const Context &context) const @@ -1455,7 +1462,7 @@ void tst_Dumpers::dumper() parent = parentIName(parent); if (parent.isEmpty()) break; - expandedINames.insert("local." + parent); + expandedINames.insert(parent); } } @@ -1670,7 +1677,7 @@ void tst_Dumpers::dumper() for (int i = data.checks.size(); --i >= 0; ) { Check check = data.checks.at(i); - QString iname = "local." + check.iname; + const QString iname = check.iname; WatchItem *item = static_cast(local.findAnyChild([iname](Utils::TreeItem *item) { return static_cast(item)->internalName() == iname; })); @@ -6985,6 +6992,14 @@ void tst_Dumpers::dumper_data() + Check("c", FloatValue("0"), TypeDef("double", "long double")) + Check("d", FloatValue("0.5"), TypeDef("double", "long double")); + QTest::newRow("WatchList") + << Data("", "") + + Watcher("watch.1", "42;43") + + Check("watch.1", "42;43", "<2 items>", "") + + Check("watch.1.0", "42", "42", "int") + + Check("watch.1.1", "43", "43", "int"); + + #ifdef Q_OS_LINUX QTest::newRow("StaticMembersInLib") // We don't seem to have such in the public interface. diff --git a/tests/auto/environment/tst_environment.cpp b/tests/auto/environment/tst_environment.cpp index 1fc8ae07301..3a835df46d3 100644 --- a/tests/auto/environment/tst_environment.cpp +++ b/tests/auto/environment/tst_environment.cpp @@ -29,6 +29,8 @@ using namespace Utils; +Q_DECLARE_METATYPE(Utils::OsType) + class tst_Environment : public QObject { Q_OBJECT @@ -55,6 +57,9 @@ private slots: void environmentUnsetUnknownWindows(); void environmentUnsetUnknownUnix(); + void find_data(); + void find(); + private: Environment env; }; @@ -247,6 +252,38 @@ void tst_Environment::environmentUnsetUnknownUnix() QCOMPARE(env.toStringList(), QStringList({"Foo=bar", "Hi=HO"})); } +void tst_Environment::find_data() +{ + QTest::addColumn("osType"); + QTest::addColumn("contains"); + QTest::addColumn("variable"); + + + QTest::newRow("win") << Utils::OsTypeWindows << true << "foo"; + QTest::newRow("win") << Utils::OsTypeWindows << true << "Foo"; + QTest::newRow("lin") << Utils::OsTypeLinux << true << "Foo"; + QTest::newRow("lin") << Utils::OsTypeLinux << false << "foo"; +} + +void tst_Environment::find() +{ + QFETCH(Utils::OsType, osType); + QFETCH(bool, contains); + QFETCH(QString, variable); + + + Environment env(QStringList({"Foo=bar", "Hi=HO"}), osType); + + auto end = env.constEnd(); + auto it = env.constFind(variable); + + QCOMPARE((end != it), contains); + + if (contains) + QCOMPARE(it.value(), "bar"); + +} + QTEST_MAIN(tst_Environment) #include "tst_environment.moc" diff --git a/tests/manual/qml/testfiles_quick2/states.qml b/tests/manual/qml/testfiles_quick2/states.qml index b385b00acda..97ff32143ac 100644 --- a/tests/manual/qml/testfiles_quick2/states.qml +++ b/tests/manual/qml/testfiles_quick2/states.qml @@ -29,6 +29,12 @@ Rectangle { id: rect width: 200 height: 200 + Image { + id: image1 + x: 41 + y: 46 + source: "images/qtcreator.png" + } Text { id: textItem x: 66 @@ -43,7 +49,7 @@ Rectangle { color: "blue" } PropertyChanges { - target: text + target: textItem text: "State1" } }, @@ -54,16 +60,9 @@ Rectangle { color: "gray" } PropertyChanges { - target: text + target: textItem text: "State2" } } ] - - Image { - id: image1 - x: 41 - y: 46 - source: "images/qtcreator.png" - } } diff --git a/tests/system/objects.map b/tests/system/objects.map index 56d1a346b9a..388424259bd 100644 --- a/tests/system/objects.map +++ b/tests/system/objects.map @@ -62,7 +62,7 @@ :Dialog_Debugger::Internal::SymbolPathsDialog {name='Debugger__Internal__SymbolPathsDialog' type='Debugger::Internal::SymbolPathsDialog' visible='1' windowTitle='Dialog'} :Dialog_QmlJSEditor::Internal::ComponentNameDialog {name='QmlJSEditor__Internal__ComponentNameDialog' type='QmlJSEditor::Internal::ComponentNameDialog' visible='1' windowTitle='Move Component into Separate File'} :Edit Environment_ProjectExplorer::EnvironmentItemsDialog {type='ProjectExplorer::EnvironmentItemsDialog' unnamed='1' visible='1' windowTitle='Edit Environment'} -:Events.QmlProfilerEventsTable_QmlProfiler::Internal::QmlProfilerEventsMainView {container=':Qt Creator.Events_QDockWidget' name='QmlProfilerEventsTable' type='QmlProfiler::Internal::QmlProfilerStatisticsMainView' visible='1'} +:Events.QmlProfilerEventsTable_QmlProfiler::Internal::QmlProfilerStatisticsMainView {container=':Qt Creator.Events_QDockWidget' name='QmlProfilerEventsTable' type='QmlProfiler::Internal::QmlProfilerStatisticsMainView' visible='1'} :Executable:_Utils::PathChooser {buddy=':scrollArea.Executable:_QLabel' type='Utils::PathChooser' unnamed='1' visible='1'} :Failed to start application_QMessageBox {type='QMessageBox' unnamed='1' visible='1' windowTitle='Failed to start application'} :File has been removed.Close_QPushButton {text='Close' type='QPushButton' unnamed='1' visible='1' window=':File has been removed_QMessageBox'} diff --git a/tests/system/suite_debugger/tst_simple_analyze/test.py b/tests/system/suite_debugger/tst_simple_analyze/test.py index 5de123db4d5..07166a8bf4d 100644 --- a/tests/system/suite_debugger/tst_simple_analyze/test.py +++ b/tests/system/suite_debugger/tst_simple_analyze/test.py @@ -107,7 +107,7 @@ def performTest(workingDir, projectName, targetCount, availableConfigs): (colPercent, colTotal, colSelfPercent, colSelf, colCalls, colMean, colMedian, colLongest, colShortest) = range(2, 11) model = waitForObject(":Events.QmlProfilerEventsTable_QmlProfiler::" - "Internal::QmlProfilerEventsMainView").model() + "Internal::QmlProfilerStatisticsMainView").model() compareEventsTab(model, "events_qt5.tsv") test.compare(dumpItems(model, column=colPercent)[0], '100.00 %') # cannot run following test on colShortest (unstable) diff --git a/tests/unit/mockup/projectexplorer/project.h b/tests/unit/mockup/projectexplorer/project.h new file mode 100644 index 00000000000..ea040fbc490 --- /dev/null +++ b/tests/unit/mockup/projectexplorer/project.h @@ -0,0 +1,41 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include + +#include + +namespace ProjectExplorer { + +class Project : public QObject { +public: + Utils::FileName projectDirectory() const { + return Utils::FileName(); + } +}; + +}