Merge "Merge remote-tracking branch 'origin/4.6'"

This commit is contained in:
Eike Ziller
2018-02-01 10:13:42 +00:00
committed by The Qt Project
138 changed files with 1554 additions and 781 deletions

View File

@@ -277,6 +277,29 @@ http://llvm.org/docs/GettingStarted.html#git-mirror:
Qt Creator includes the following third-party components, Qt Creator includes the following third-party components,
we thank the authors who made this possible: 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 ### Reference implementation for std::experimental::optional
https://github.com/akrzemi1/Optional https://github.com/akrzemi1/Optional

147
dist/changes-4.6.0.md vendored Normal file
View File

@@ -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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

After

Width:  |  Height:  |  Size: 22 KiB

View File

@@ -75,8 +75,8 @@
useful if the code contains typos, for example. useful if the code contains typos, for example.
Clang keeps up with the development of the C++ language. At the time of this 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 writing, it supports C++98/03, C++11, C++14, C++17, C89, C99, Objective-C,
Objective-C++. and Objective-C++.
On the downside, for large projects using Clang as code model is slower than 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, using the built-in code model. Clang does not need to generate object files,
@@ -94,11 +94,27 @@
\li Syntactic and semantic highlighting \li Syntactic and semantic highlighting
\li Diagnostics \li Diagnostics
\li Tooltips \li Tooltips
\li Clang-Tidy and Clazy checks
\li Renaming of local symbols
\endlist \endlist
To use the plugin, you must activate it and configure it in \QC. 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 \section1 Activating Clang Code Model
If you build \QC yourself, ensure that the plugin is also built, as 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 {Options to Request or Suppress Warnings} or the GCC or Clang
manual pages. manual pages.
\li In the \uicontrol {Clang Plugins} field, select the Clang-Tidy and
Clazy checks to perform.
\endlist \endlist
You can specify Clang settings at project level in the build settings of You can specify Clang settings at project level in the build settings of

View File

@@ -2851,6 +2851,9 @@
\li Locating files belonging to your project (\c {p}), such as source, \li Locating files belonging to your project (\c {p}), such as source,
header resource, and \c {.ui} files, or to any project (\c {a}) 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 \li Locating class (\c {c}), enum, and function (m) definitions in your
project or anywhere referenced from your project (\c {:}) project or anywhere referenced from your project (\c {:})
@@ -2874,6 +2877,8 @@
\li Executing version control system commands (\c {git}). For more \li Executing version control system commands (\c {git}). For more
information, see \l{Using Version Control Systems} information, see \l{Using Version Control Systems}
\li Triggering menu items from the main menu (\c {t})
\li Running external tools (\c x) \li Running external tools (\c x)
\endlist \endlist
@@ -2914,6 +2919,10 @@
followed by \key Space, followed by path and file name, and then press followed by \key Space, followed by path and file name, and then press
\key Enter. \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 By default, the following filters are enabled and you do not need to use
their prefixes explicitly: their prefixes explicitly:

View File

@@ -98,6 +98,9 @@
\image qtcreator-welcome-session.png \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 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 appears when you move the mouse cursor over the session name. Select actions
to clone, rename, and delete sessions. to clone, rename, and delete sessions.

View File

@@ -261,7 +261,11 @@
\image qtcreator-filesystem-view.png \image qtcreator-filesystem-view.png
By default, the contents of the directory that contains the file currently 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 file system, select \uicontrol Computer in the menu (1). Select
\uicontrol Home to move to the user's home directory. Further, you can \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 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 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. \li Display the contents of a particular directory in the view.
\endlist \endlist

View File

@@ -1,6 +1,6 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2016 The Qt Company Ltd. ** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/ ** Contact: https://www.qt.io/licensing/
** **
** This file is part of the Qt Creator documentation. ** This file is part of the Qt Creator documentation.
@@ -124,6 +124,9 @@
\uicontrol {Fixup Previous Commit}. This operation is done using interactive \uicontrol {Fixup Previous Commit}. This operation is done using interactive
rebase. In case of conflicts, a merge tool is suggested. 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 To change a series of commits in the local repository, select
\uicontrol Tools > \uicontrol Git > \uicontrol {Local Repository} > \uicontrol Tools > \uicontrol Git > \uicontrol {Local Repository} >
\uicontrol {Interactive Rebase}. You can reorder or discard commits, squash \uicontrol {Interactive Rebase}. You can reorder or discard commits, squash

View File

@@ -1,6 +1,6 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2016 The Qt Company Ltd. ** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/ ** Contact: https://www.qt.io/licensing/
** **
** This file is part of the Qt Creator documentation. ** This file is part of the Qt Creator documentation.
@@ -234,6 +234,9 @@
show annotation views of previous versions (see \l{Annotating Files}). 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 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 \section2 Annotating Files
Annotation views are obtained by selecting \uicontrol{Annotate} or \uicontrol{Blame}. 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 The same context menu is available when right-clicking on a version
identifier in the file log view of a single file. 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 \section2 Committing Changes
Once you have finished making changes, submit them to the version control Once you have finished making changes, submit them to the version control

View File

@@ -16,7 +16,10 @@ function readOutput(executable, args)
function readListOutput(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) function isSuitableLLVMConfig(llvmConfigCandidate, qtcFunctions)

View File

@@ -9,6 +9,7 @@ Module {
property bool enableUnitTests: false property bool enableUnitTests: false
property bool enableProjectFileUpdates: true property bool enableProjectFileUpdates: true
property bool installApiHeaders: false property bool installApiHeaders: false
property bool enableBundledQt: false
property string libInstallDir: qtc.ide_library_path property string libInstallDir: qtc.ide_library_path
property stringList libRPaths: qbs.targetOS.contains("macos") property stringList libRPaths: qbs.targetOS.contains("macos")
? ["@loader_path/" + FileInfo.relativePath('/' + appInstallDir, '/' + libInstallDir)] ? ["@loader_path/" + FileInfo.relativePath('/' + appInstallDir, '/' + libInstallDir)]

View File

@@ -118,7 +118,7 @@ macx {
} else { } else {
BINDIST_SOURCE = "$(INSTALL_ROOT)$$QTC_PREFIX" BINDIST_SOURCE = "$(INSTALL_ROOT)$$QTC_PREFIX"
BINDIST_EXCLUDE_ARG = "--exclude-toplevel" 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 deployqt.depends = install
win32 { win32 {
deployartifacts.depends = install deployartifacts.depends = install

View File

@@ -43,7 +43,7 @@ debug_build = False
encoding = locale.getdefaultlocale()[1] encoding = locale.getdefaultlocale()[1]
def usage(): def usage():
print("Usage: %s <creator_install_dir> [qmake_path]" % os.path.basename(sys.argv[0])) print("Usage: %s <existing_qtcreator_binary> [qmake_path]" % os.path.basename(sys.argv[0]))
def which(program): def which(program):
def is_exe(fpath): def is_exe(fpath):
@@ -77,9 +77,6 @@ def is_debug(fpath):
output = subprocess.check_output(['dumpbin', '/imports', fpath]) output = subprocess.check_output(['dumpbin', '/imports', fpath])
return coredebug.search(output.decode(encoding)) != None 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): def op_failed(details = None):
if details != None: if details != None:
print(details) print(details)
@@ -274,11 +271,16 @@ def main():
ignoreErrors = True ignoreErrors = True
print("Note: Ignoring all errors") 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() usage()
sys.exit(2) 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(): if common.is_linux_platform():
qt_deploy_prefix = os.path.join(install_dir, 'lib', 'Qt') qt_deploy_prefix = os.path.join(install_dir, 'lib', 'Qt')
else: else:
@@ -307,12 +309,14 @@ def main():
QT_INSTALL_QML = qt_install_info['QT_INSTALL_QML'] QT_INSTALL_QML = qt_install_info['QT_INSTALL_QML']
QT_INSTALL_TRANSLATIONS = qt_install_info['QT_INSTALL_TRANSLATIONS'] 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'] imports = ['Qt', 'QtWebKit']
if common.is_windows_platform(): if common.is_windows_platform():
global debug_build global debug_build
debug_build = is_debug_build(install_dir) debug_build = is_debug(qtcreator_binary)
if common.is_windows_platform(): 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) copy_qt_libs(qt_deploy_prefix, QT_INSTALL_BINS, QT_INSTALL_BINS, QT_INSTALL_PLUGINS, QT_INSTALL_IMPORTS, QT_INSTALL_QML, plugins, imports)

View File

@@ -41,8 +41,9 @@ use warnings;
while (my $line = <STDIN>) { while (my $line = <STDIN>) {
chomp($line); chomp($line);
# --- extract file name based matching: # --- extract file name based matching:
# D:/.../qaxbase.cpp:3231: warning: Cannot tie this documentation to anything # Qt 5.10: D:/.../qaxbase.cpp:3231: warning: Cannot tie this documentation to anything
if ($line =~ /^(..[^:]*):(\d+): warning: (.*)$/) { # Qt 5.11: D:/.../qaxbase.cpp:3231: (qdoc) warning: Cannot tie this documentation to anything
if ($line =~ /^(..[^:]*):(\d+): (?:\(qdoc\) )?warning: (.*)$/) {
my $fileName = $1; my $fileName = $1;
my $lineNumber = $2; my $lineNumber = $2;
my $text = $3; my $text = $3;

View File

@@ -11,7 +11,7 @@ Module {
"QmlProject/Project 1.1" "QmlProject/Project 1.1"
] ]
Property { name: "sourceDirectory"; type: "string" } Property { name: "sourceDirectory"; type: "string" }
Property { name: "targetDirectory": type: "string" } Property { name: "targetDirectory"; type: "string" }
Property { name: "mainFile"; type: "string" } Property { name: "mainFile"; type: "string" }
Property { name: "importPaths"; type: "string"; isList: true } Property { name: "importPaths"; type: "string"; isList: true }
Property { name: "content"; type: "QmlProjectItem"; isList: true } Property { name: "content"; type: "QmlProjectItem"; isList: true }
@@ -70,4 +70,4 @@ Module {
] ]
Property { name: "filter"; type: "string" } Property { name: "filter"; type: "string" }
} }
} }

View File

@@ -155,6 +155,12 @@ Item {
} }
checkable: true checkable: true
} }
Controls.MenuItem {
text: qsTr("Insert keyframe")
visible: hasActiveTimeline
onTriggered: insertKeyframe(backendValue.name)
}
} }
} }
} }

View File

@@ -6,6 +6,7 @@
"trDescription": "Creates a scratch model using a temporary file.", "trDescription": "Creates a scratch model using a temporary file.",
"trDisplayName": "Scratch Model", "trDisplayName": "Scratch Model",
"trDisplayCategory": "Modeling", "trDisplayCategory": "Modeling",
"iconText": "qmodel",
"platformIndependent": true, "platformIndependent": true,
"enabled": "%{JS: [ %{Plugins} ].indexOf('ModelEditor') >= 0}", "enabled": "%{JS: [ %{Plugins} ].indexOf('ModelEditor') >= 0}",

View File

@@ -1,10 +1,12 @@
cmake_minimum_required(VERSION 2.8.12) cmake_minimum_required(VERSION 3.1)
project(%{ProjectName} LANGUAGES CXX) project(%{ProjectName} LANGUAGES CXX)
set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON) set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON) set(CMAKE_AUTORCC ON)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(Qt5 COMPONENTS Core Quick REQUIRED) find_package(Qt5 COMPONENTS Core Quick REQUIRED)

View File

@@ -57589,7 +57589,7 @@ Má se to zkusit ještě jednou?</translation>
</message> </message>
</context> </context>
<context> <context>
<name>QmlProfiler::Internal::QmlProfilerEventsMainView</name> <name>QmlProfiler::Internal::QmlProfilerStatisticsMainView</name>
<message> <message>
<source>Location</source> <source>Location</source>
<translation>Umístění</translation> <translation>Umístění</translation>

View File

@@ -58942,7 +58942,7 @@ Voulez-vous la tuer ?</translation>
</message> </message>
</context> </context>
<context> <context>
<name>QmlProfiler::Internal::QmlProfilerEventsMainView</name> <name>QmlProfiler::Internal::QmlProfilerStatisticsMainView</name>
<message> <message>
<source>Location</source> <source>Location</source>
<translation>Emplacement</translation> <translation>Emplacement</translation>

View File

@@ -30492,7 +30492,7 @@ Do you want to kill it?</source>
</message> </message>
</context> </context>
<context> <context>
<name>QmlProfiler::Internal::QmlProfilerEventsMainView</name> <name>QmlProfiler::Internal::QmlProfilerStatisticsMainView</name>
<message> <message>
<source>Location</source> <source>Location</source>
<translation type="vanished">Розташування</translation> <translation type="vanished">Розташування</translation>

View File

@@ -55655,7 +55655,7 @@ Do you want to retry?</source>
</message> </message>
</context> </context>
<context> <context>
<name>QmlProfiler::Internal::QmlProfilerEventsMainView</name> <name>QmlProfiler::Internal::QmlProfilerStatisticsMainView</name>
<message> <message>
<source>Location</source> <source>Location</source>
<translation></translation> <translation></translation>

View File

@@ -32076,7 +32076,7 @@ Do you want to kill it?</source>
</message> </message>
</context> </context>
<context> <context>
<name>QmlProfiler::Internal::QmlProfilerEventsMainView</name> <name>QmlProfiler::Internal::QmlProfilerStatisticsMainView</name>
<message> <message>
<source>Location</source> <source>Location</source>
<translation></translation> <translation></translation>

View File

@@ -153,9 +153,10 @@ Item {
spacing: innerMargin spacing: innerMargin
columns: 2 columns: 2
property int minimumWidth: { property int minimumWidth: {
// max(width of longest label * 2, minimumInnerWidth)
var result = minimumInnerWidth; var result = minimumInnerWidth;
for (var i = 0; i < children.length; ++i) for (var i = 0; i < children.length; i += 2)
result = Math.max(children[i].x, result); result = Math.max(children[i].implicitWidth * 2 + innerMargin, result);
return result + 2 * outerMargin; return result + 2 * outerMargin;
} }
@@ -170,8 +171,8 @@ Item {
property bool isLabel: index % 2 === 0 property bool isLabel: index % 2 === 0
font.bold: isLabel font.bold: isLabel
elide: Text.ElideRight elide: Text.ElideRight
width: text === "" ? 0 : (isLabel ? implicitWidth : width: (text === "" || isLabel)
(dragHandle.x - x - innerMargin)) ? implicitWidth : (dragHandle.x - col.minimumWidth / 2 - innerMargin)
text: isLabel ? (modelData + ":") : modelData text: isLabel ? (modelData + ":") : modelData
color: contentTextColor color: contentTextColor
} }

View File

@@ -176,9 +176,10 @@ Item {
spacing: 5 spacing: 5
columns: 2 columns: 2
property int minimumWidth: { property int minimumWidth: {
// max(width of longest label * 2, 150)
var result = 150; var result = 150;
for (var i = 0; i < children.length; ++i) for (var i = 0; i < children.length; i += 2)
result = Math.max(children[i].x, result); result = Math.max(children[i].implicitWidth * 2 + spacing, result);
return result + 20; return result + 20;
} }
@@ -190,7 +191,7 @@ Item {
Repeater { Repeater {
model: eventInfo model: eventInfo
Detail { Detail {
valueWidth: dragHandle.x - x - 15 valueWidth: (dragHandle.x - col.minimumWidth / 2 - col.spacing)
isLabel: index % 2 === 0 isLabel: index % 2 === 0
text: (content === undefined) ? "" : (isLabel ? (content + ":") : content) text: (content === undefined) ? "" : (isLabel ? (content + ":") : content)
} }

View File

@@ -500,7 +500,7 @@ Environment::const_iterator Environment::constEnd() const
Environment::const_iterator Environment::constFind(const QString &name) 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 int Environment::size() const
@@ -567,6 +567,11 @@ bool Environment::hasKey(const QString &key) const
return m_values.contains(key); return m_values.contains(key);
} }
OsType Environment::osType() const
{
return m_osType;
}
QString Environment::userName() const QString Environment::userName() const
{ {
return value(QString::fromLatin1(m_osType == OsTypeWindows ? "USERNAME" : "USER")); return value(QString::fromLatin1(m_osType == OsTypeWindows ? "USERNAME" : "USER"));

View File

@@ -91,6 +91,7 @@ public:
/// Return the Environment changes necessary to modify this into the other environment. /// Return the Environment changes necessary to modify this into the other environment.
QList<EnvironmentItem> diff(const Environment &other, bool checkAppendPrepend = false) const; QList<EnvironmentItem> diff(const Environment &other, bool checkAppendPrepend = false) const;
bool hasKey(const QString &key) const; bool hasKey(const QString &key) const;
OsType osType() const;
QString userName() const; QString userName() const;

View File

@@ -364,6 +364,13 @@ void EnvironmentModel::setUserChanges(QList<EnvironmentItem> list)
name = name.trimmed(); name = name.trimmed();
if (name.startsWith(QLatin1String("export "))) if (name.startsWith(QLatin1String("export ")))
name = name.mid(7).trimmed(); 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(); d->updateResultEnvironment();

View File

@@ -31,6 +31,7 @@
#include <cpptools/cppmodelmanager.h> #include <cpptools/cppmodelmanager.h>
#include <projectexplorer/session.h> #include <projectexplorer/session.h>
#include <utils/algorithm.h> #include <utils/algorithm.h>
#include <utils/asconst.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
namespace Autotest { namespace Autotest {
@@ -122,35 +123,67 @@ TestConfiguration *GTestTreeItem::debugConfiguration() const
return config; return config;
} }
QList<TestConfiguration *> GTestTreeItem::getAllTestConfigurations() const struct TestCases
{
QStringList filters;
int testSetCount = 0;
QSet<QString> internalTargets;
};
static void collectTestInfo(const GTestTreeItem *item,
QHash<QString, TestCases> &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<const GTestTreeItem *>(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<TestConfiguration *> GTestTreeItem::getTestConfigurations(bool ignoreCheckState) const
{ {
QList<TestConfiguration *> result; QList<TestConfiguration *> result;
ProjectExplorer::Project *project = ProjectExplorer::SessionManager::startupProject(); ProjectExplorer::Project *project = ProjectExplorer::SessionManager::startupProject();
if (!project || type() != Root) if (!project || type() != Root)
return result; return result;
QHash<QString, int> proFilesWithTestSets; QHash<QString, TestCases> testCasesForProFile;
QHash<QString, QSet<QString> > proFilesWithInternalTargets;
for (int row = 0, count = childCount(); row < count; ++row) { for (int row = 0, count = childCount(); row < count; ++row) {
const GTestTreeItem *child = static_cast<const GTestTreeItem *>(childItem(row)); auto child = static_cast<const GTestTreeItem *>(childItem(row));
collectTestInfo(child, testCasesForProFile, ignoreCheckState);
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());
}
} }
QHash<QString, int>::ConstIterator it = proFilesWithTestSets.begin(); for (auto it = testCasesForProFile.begin(), end = testCasesForProFile.end(); it != end; ++it) {
QHash<QString, int>::ConstIterator end = proFilesWithTestSets.end(); for (const QString &target : Utils::asConst(it.value().internalTargets)) {
for ( ; it != end; ++it) {
const QSet<QString> &internalTargets = proFilesWithInternalTargets[it.key()];
for (const QString &target : internalTargets) {
GTestConfiguration *tc = new GTestConfiguration; 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->setProjectFile(it.key());
tc->setProject(project); tc->setProject(project);
tc->setInternalTarget(target); tc->setInternalTarget(target);
@@ -161,69 +194,14 @@ QList<TestConfiguration *> GTestTreeItem::getAllTestConfigurations() const
return result; return result;
} }
struct TestCases QList<TestConfiguration *> GTestTreeItem::getAllTestConfigurations() const
{ {
QStringList filters; return getTestConfigurations(true);
int additionalTestCaseCount = 0; }
};
QList<TestConfiguration *> GTestTreeItem::getSelectedTestConfigurations() const QList<TestConfiguration *> GTestTreeItem::getSelectedTestConfigurations() const
{ {
QList<TestConfiguration *> result; return getTestConfigurations(false);
ProjectExplorer::Project *project = ProjectExplorer::SessionManager::startupProject();
if (!project || type() != Root)
return result;
QHash<QString, TestCases> proFilesWithCheckedTestSets;
QHash<QString, QSet<QString> > proFilesWithInternalTargets;
for (int row = 0, count = childCount(); row < count; ++row) {
const GTestTreeItem *child = static_cast<const GTestTreeItem *>(childItem(row));
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<QString, TestCases>::ConstIterator it = proFilesWithCheckedTestSets.begin();
QHash<QString, TestCases>::ConstIterator end = proFilesWithCheckedTestSets.end();
for ( ; it != end; ++it) {
const QSet<QString> &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;
} }
TestTreeItem *GTestTreeItem::find(const TestParseResult *result) TestTreeItem *GTestTreeItem::find(const TestParseResult *result)

View File

@@ -71,6 +71,7 @@ public:
private: private:
bool modifyTestSetContent(const GTestParseResult *result); bool modifyTestSetContent(const GTestParseResult *result);
QList<TestConfiguration *> getTestConfigurations(bool ignoreCheckState) const;
GTestTreeItem::TestStates m_state; GTestTreeItem::TestStates m_state;
}; };

View File

@@ -38,7 +38,7 @@ QtTestTreeItem::QtTestTreeItem(const QString &name, const QString &filePath, Tes
: TestTreeItem(name, filePath, type) : TestTreeItem(name, filePath, type)
{ {
if (type == TestDataTag) if (type == TestDataTag)
setChecked(Qt::Checked); setData(0, Qt::Checked, Qt::CheckStateRole);
} }
QVariant QtTestTreeItem::data(int column, int role) const QVariant QtTestTreeItem::data(int column, int role) const
@@ -139,6 +139,53 @@ TestConfiguration *QtTestTreeItem::testConfiguration() const
return config; return config;
} }
static void fillTestConfigurationsFromCheckState(const TestTreeItem *item,
QList<TestConfiguration *> &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<QtTestConfiguration *>(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 TestConfiguration *QtTestTreeItem::debugConfiguration() const
{ {
QtTestConfiguration *config = static_cast<QtTestConfiguration *>(testConfiguration()); QtTestConfiguration *config = static_cast<QtTestConfiguration *>(testConfiguration());
@@ -157,13 +204,19 @@ QList<TestConfiguration *> QtTestTreeItem::getAllTestConfigurations() const
for (int row = 0, count = childCount(); row < count; ++row) { for (int row = 0, count = childCount(); row < count; ++row) {
const TestTreeItem *child = childItem(row); const TestTreeItem *child = childItem(row);
TestConfiguration *tc = nullptr;
TestConfiguration *tc = new QtTestConfiguration(); if (child->type() == TestCase) {
tc->setTestCaseCount(child->childCount()); tc = child->testConfiguration();
tc->setProjectFile(child->proFile()); QTC_ASSERT(tc, continue);
tc->setProject(project); result << tc;
tc->setInternalTargets(child->internalTargets()); } else if (child->type() == GroupNode) {
result << tc; 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; return result;
} }
@@ -175,49 +228,8 @@ QList<TestConfiguration *> QtTestTreeItem::getSelectedTestConfigurations() const
if (!project || type() != Root) if (!project || type() != Root)
return result; return result;
QtTestConfiguration *testConfiguration = nullptr; for (int row = 0, count = childCount(); row < count; ++row)
fillTestConfigurationsFromCheckState(childItem(row), result);
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;
}
}
return result; return result;
} }

View File

@@ -153,6 +153,43 @@ TestConfiguration *QuickTestTreeItem::testConfiguration() const
return config; return config;
} }
static void testConfigurationFromCheckState(const TestTreeItem *item,
QHash<QString, QuickTestConfiguration *> &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 TestConfiguration *QuickTestTreeItem::debugConfiguration() const
{ {
QuickTestConfiguration *config = static_cast<QuickTestConfiguration *>(testConfiguration()); QuickTestConfiguration *config = static_cast<QuickTestConfiguration *>(testConfiguration());
@@ -161,6 +198,17 @@ TestConfiguration *QuickTestTreeItem::debugConfiguration() const
return config; return config;
} }
struct Tests {
int testCount = 0;
QSet<QString> internalTargets;
};
static void addTestsForItem(Tests &tests, const TestTreeItem *item)
{
tests.testCount += item->childCount();
tests.internalTargets = item->internalTargets();
}
QList<TestConfiguration *> QuickTestTreeItem::getAllTestConfigurations() const QList<TestConfiguration *> QuickTestTreeItem::getAllTestConfigurations() const
{ {
QList<TestConfiguration *> result; QList<TestConfiguration *> result;
@@ -169,8 +217,7 @@ QList<TestConfiguration *> QuickTestTreeItem::getAllTestConfigurations() const
if (!project || type() != Root) if (!project || type() != Root)
return result; return result;
QHash<QString, int> foundProFiles; QHash<QString, Tests> testsForProfile;
QHash<QString, QSet<QString> > proFilesWithTargets;
for (int row = 0, count = childCount(); row < count; ++row) { for (int row = 0, count = childCount(); row < count; ++row) {
const TestTreeItem *child = childItem(row); const TestTreeItem *child = childItem(row);
// unnamed Quick Tests must be handled separately // unnamed Quick Tests must be handled separately
@@ -178,25 +225,29 @@ QList<TestConfiguration *> QuickTestTreeItem::getAllTestConfigurations() const
for (int childRow = 0, ccount = child->childCount(); childRow < ccount; ++ childRow) { for (int childRow = 0, ccount = child->childCount(); childRow < ccount; ++ childRow) {
const TestTreeItem *grandChild = child->childItem(childRow); const TestTreeItem *grandChild = child->childItem(childRow);
const QString &proFile = grandChild->proFile(); const QString &proFile = grandChild->proFile();
foundProFiles.insert(proFile, foundProFiles[proFile] + 1); ++(testsForProfile[proFile].testCount);
proFilesWithTargets.insert(proFile, grandChild->internalTargets()); testsForProfile[proFile].internalTargets = grandChild->internalTargets();
} }
continue; continue;
} }
// named Quick Test // named Quick Test
const QString &proFile = child->proFile(); if (child->type() == TestCase) {
foundProFiles.insert(proFile, foundProFiles[proFile] + child->childCount()); addTestsForItem(testsForProfile[child->proFile()], child);
proFilesWithTargets.insert(proFile, child->internalTargets()); } 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 // create TestConfiguration for each project file
QHash<QString, int>::ConstIterator it = foundProFiles.begin(); for (auto it = testsForProfile.begin(), end = testsForProfile.end(); it != end; ++it) {
QHash<QString, int>::ConstIterator end = foundProFiles.end();
for ( ; it != end; ++it) {
QuickTestConfiguration *tc = new QuickTestConfiguration; QuickTestConfiguration *tc = new QuickTestConfiguration;
tc->setTestCaseCount(it.value()); tc->setTestCaseCount(it.value().testCount);
tc->setProjectFile(it.key()); tc->setProjectFile(it.key());
tc->setProject(project); tc->setProject(project);
tc->setInternalTargets(proFilesWithTargets[it.key()]); tc->setInternalTargets(it.value().internalTargets);
result << tc; result << tc;
} }
return result; return result;
@@ -209,7 +260,6 @@ QList<TestConfiguration *> QuickTestTreeItem::getSelectedTestConfigurations() co
if (!project || type() != Root) if (!project || type() != Root)
return result; return result;
QuickTestConfiguration *tc = nullptr;
QHash<QString, QuickTestConfiguration *> foundProFiles; QHash<QString, QuickTestConfiguration *> foundProFiles;
for (int row = 0, count = childCount(); row < count; ++row) { for (int row = 0, count = childCount(); row < count; ++row) {
@@ -219,39 +269,10 @@ QList<TestConfiguration *> QuickTestTreeItem::getSelectedTestConfigurations() co
continue; continue;
// named Quick Tests // named Quick Tests
switch (child->checked()) { testConfigurationFromCheckState(child, foundProFiles);
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;
}
} }
QHash<QString, QuickTestConfiguration *>::ConstIterator it = foundProFiles.begin();
QHash<QString, QuickTestConfiguration *>::ConstIterator end = foundProFiles.end(); for (auto it = foundProFiles.begin(), end = foundProFiles.end(); it != end; ++it) {
for ( ; it != end; ++it) {
QuickTestConfiguration *config = it.value(); QuickTestConfiguration *config = it.value();
if (!config->unnamedOnly()) if (!config->unnamedOnly())
result << config; result << config;
@@ -327,6 +348,12 @@ bool QuickTestTreeItem::isGroupNodeFor(const TestTreeItem *other) const
return TestTreeItem::isGroupNodeFor(other); return TestTreeItem::isGroupNodeFor(other);
} }
bool QuickTestTreeItem::removeOnSweepIfEmpty() const
{
return TestTreeItem::removeOnSweepIfEmpty()
|| (type() == TestCase && name().isEmpty()); // remove pseudo item '<unnamed>'
}
TestTreeItem *QuickTestTreeItem::createParentGroupNode() const TestTreeItem *QuickTestTreeItem::createParentGroupNode() const
{ {
if (filePath().isEmpty() || name().isEmpty()) if (filePath().isEmpty() || name().isEmpty())

View File

@@ -48,6 +48,7 @@ public:
bool modify(const TestParseResult *result) override; bool modify(const TestParseResult *result) override;
bool lessThan(const TestTreeItem *other, SortMode mode) const override; bool lessThan(const TestTreeItem *other, SortMode mode) const override;
bool isGroupNodeFor(const TestTreeItem *other) const override; bool isGroupNodeFor(const TestTreeItem *other) const override;
bool removeOnSweepIfEmpty() const override;
TestTreeItem *createParentGroupNode() const override; TestTreeItem *createParentGroupNode() const override;
QSet<QString> internalTargets() const override; QSet<QString> internalTargets() const override;
private: private:

View File

@@ -55,13 +55,11 @@ void TestResultDelegate::paint(QPainter *painter, const QStyleOptionViewItem &op
{ {
QStyleOptionViewItem opt = option; QStyleOptionViewItem opt = option;
initStyleOption(&opt, index); initStyleOption(&opt, index);
painter->save();
QFontMetrics fm(opt.font); QFontMetrics fm(opt.font);
QBrush background; QBrush background;
QColor foreground; QColor foreground;
const QAbstractItemView *view = qobject_cast<const QAbstractItemView *>(opt.widget);
const bool selected = opt.state & QStyle::State_Selected; const bool selected = opt.state & QStyle::State_Selected;
if (selected) { if (selected) {
@@ -71,10 +69,14 @@ void TestResultDelegate::paint(QPainter *painter, const QStyleOptionViewItem &op
background = opt.palette.window().color(); background = opt.palette.window().color();
foreground = opt.palette.text().color(); foreground = opt.palette.text().color();
} }
auto resultFilterModel = qobject_cast<const TestResultFilterModel *>(index.model());
if (!resultFilterModel)
return;
painter->save();
painter->fillRect(opt.rect, background); painter->fillRect(opt.rect, background);
painter->setPen(foreground); painter->setPen(foreground);
TestResultFilterModel *resultFilterModel = static_cast<TestResultFilterModel *>(view->model());
LayoutPositions positions(opt, resultFilterModel); LayoutPositions positions(opt, resultFilterModel);
const TestResult *testResult = resultFilterModel->testResult(index); const TestResult *testResult = resultFilterModel->testResult(index);
QTC_ASSERT(testResult, painter->restore();return); QTC_ASSERT(testResult, painter->restore();return);

View File

@@ -56,7 +56,7 @@ private:
class LayoutPositions class LayoutPositions
{ {
public: public:
LayoutPositions(QStyleOptionViewItem &options, TestResultFilterModel *filterModel) LayoutPositions(QStyleOptionViewItem &options, const TestResultFilterModel *filterModel)
: m_totalWidth(options.rect.width()), : m_totalWidth(options.rect.width()),
m_top(options.rect.top()), m_top(options.rect.top()),
m_bottom(options.rect.bottom()) m_bottom(options.rect.bottom())

View File

@@ -106,9 +106,9 @@ QVariant TestTreeItem::data(int /*column*/, int role) const
bool TestTreeItem::setData(int /*column*/, const QVariant &data, int role) bool TestTreeItem::setData(int /*column*/, const QVariant &data, int role)
{ {
if (role == Qt::CheckStateRole) { if (role == Qt::CheckStateRole) {
Qt::CheckState old = checked(); Qt::CheckState old = m_checked;
setChecked((Qt::CheckState)data.toInt()); m_checked = (Qt::CheckState)data.toInt();
return checked() != old; return m_checked != old;
} }
return false; return false;
} }
@@ -168,34 +168,6 @@ bool TestTreeItem::modifyLineAndColumn(const TestParseResult *result)
return hasBeenModified; 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 Qt::CheckState TestTreeItem::checked() const
{ {
switch (m_type) { switch (m_type) {
@@ -327,41 +299,6 @@ QSet<QString> TestTreeItem::internalTargets() const
return targets; 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) inline bool TestTreeItem::modifyFilePath(const QString &filePath)
{ {
if (m_filePath != filePath) { if (m_filePath != filePath) {

View File

@@ -89,12 +89,12 @@ public:
unsigned column() const { return m_column; } unsigned column() const { return m_column; }
QString proFile() const { return m_proFile; } QString proFile() const { return m_proFile; }
void setProFile(const QString &proFile) { m_proFile = proFile; } void setProFile(const QString &proFile) { m_proFile = proFile; }
virtual void setChecked(const Qt::CheckState checked);
virtual Qt::CheckState checked() const; virtual Qt::CheckState checked() const;
Type type() const { return m_type; } Type type() const { return m_type; }
void markForRemoval(bool mark); void markForRemoval(bool mark);
void markForRemovalRecursively(bool mark); void markForRemovalRecursively(bool mark);
virtual void markForRemovalRecursively(const QString &filePath); virtual void markForRemovalRecursively(const QString &filePath);
virtual bool removeOnSweepIfEmpty() const { return m_type == GroupNode; }
bool markedForRemoval() const { return m_status == MarkedForRemoval; } bool markedForRemoval() const { return m_status == MarkedForRemoval; }
bool newlyAdded() const { return m_status == NewlyAdded; } bool newlyAdded() const { return m_status == NewlyAdded; }
TestTreeItem *parentItem() const; TestTreeItem *parentItem() const;
@@ -123,7 +123,6 @@ protected:
const QString &file); const QString &file);
private: private:
void revalidateCheckState();
bool modifyFilePath(const QString &filePath); bool modifyFilePath(const QString &filePath);
bool modifyName(const QString &name); bool modifyName(const QString &name);
@@ -143,7 +142,7 @@ private:
QString m_proFile; QString m_proFile;
Status m_status = NewlyAdded; Status m_status = NewlyAdded;
friend class TestTreeModel; // grant access to (private) revalidateCheckState() friend class TestTreeModel; // grant access to (protected) findChildBy()
}; };
class TestCodeLocationAndType class TestCodeLocationAndType

View File

@@ -108,21 +108,18 @@ bool TestTreeModel::setData(const QModelIndex &index, const QVariant &value, int
if (item && item->setData(index.column(), value, role)) { if (item && item->setData(index.column(), value, role)) {
emit dataChanged(index, index); emit dataChanged(index, index);
if (role == Qt::CheckStateRole) { if (role == Qt::CheckStateRole) {
switch (item->type()) { Qt::CheckState checked = item->checked();
case TestTreeItem::Root: if (item->hasChildren() && checked != Qt::PartiallyChecked) {
case TestTreeItem::GroupNode: // handle the new checkstate for children as well...
case TestTreeItem::TestCase: for (Utils::TreeItem *child : *item) {
if (item->childCount() > 0) const QModelIndex &idx = indexForItem(child);
emit dataChanged(index.child(0, 0), index.child(item->childCount() - 1, 0)); setData(idx, checked ? Qt::Checked : Qt::Unchecked, Qt::CheckStateRole);
break; }
case TestTreeItem::TestFunctionOrSet:
emit dataChanged(index.parent(), index.parent());
break;
default: // avoid warning regarding unhandled enum member
break;
} }
if (item->parent() != rootItem() && item->parentItem()->checked() != checked)
revalidateCheckState(item->parentItem()); // handle parent too
return true;
} }
return true;
} }
return false; return false;
} }
@@ -254,10 +251,14 @@ bool TestTreeModel::sweepChildren(TestTreeItem *item)
if (child->type() != TestTreeItem::Root && child->markedForRemoval()) { if (child->type() != TestTreeItem::Root && child->markedForRemoval()) {
destroyItem(child); destroyItem(child);
item->revalidateCheckState(); revalidateCheckState(item);
hasChanged = true; hasChanged = true;
} else if (child->hasChildren()) { } else if (child->hasChildren()) {
hasChanged |= sweepChildren(child); hasChanged |= sweepChildren(child);
if (!child->hasChildren() && child->removeOnSweepIfEmpty()) {
destroyItem(child);
revalidateCheckState(item);
}
} else { } else {
hasChanged |= child->newlyAdded(); hasChanged |= child->newlyAdded();
} }
@@ -281,6 +282,50 @@ void TestTreeModel::insertItemInParent(TestTreeItem *item, TestTreeItem *root, b
} }
} }
parentNode->appendChild(item); 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) void TestTreeModel::onParseResultReady(const TestParseResultPtr result)
@@ -321,12 +366,6 @@ void TestTreeModel::handleParseResult(const TestParseResult *result, TestTreeIte
QTC_ASSERT(newItem, return); QTC_ASSERT(newItem, return);
insertItemInParent(newItem, parentNode, groupingEnabled); 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() void TestTreeModel::removeAllTestItems()
@@ -335,7 +374,7 @@ void TestTreeModel::removeAllTestItems()
item->removeChildren(); item->removeChildren();
TestTreeItem *testTreeItem = static_cast<TestTreeItem *>(item); TestTreeItem *testTreeItem = static_cast<TestTreeItem *>(item);
if (testTreeItem->checked() == Qt::PartiallyChecked) if (testTreeItem->checked() == Qt::PartiallyChecked)
testTreeItem->setChecked(Qt::Checked); testTreeItem->setData(0, Qt::Checked, Qt::CheckStateRole);
} }
emit testTreeModelChanged(); emit testTreeModelChanged();
} }

View File

@@ -87,8 +87,8 @@ private:
void removeTestRootNodes(); void removeTestRootNodes();
void removeFiles(const QStringList &files); void removeFiles(const QStringList &files);
bool sweepChildren(TestTreeItem *item); 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); explicit TestTreeModel(QObject *parent = 0);
void setupParsingConnections(); void setupParsingConnections();

View File

@@ -45,6 +45,13 @@ TestTreeView::TestTreeView(QWidget *parent)
Core::ICore::addContextObject(m_context); 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() void TestTreeView::selectAll()
{ {
changeCheckStateAll(Qt::Checked); changeCheckStateAll(Qt::Checked);
@@ -55,40 +62,5 @@ void TestTreeView::deselectAll()
changeCheckStateAll(Qt::Unchecked); 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<TestTreeItem *>(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<TestTreeItem *>(last.internalPointer());
if (item)
item->setChecked(checkState);
}
}
if (count == 0) {
if (auto item = static_cast<TestTreeItem *>(currentRootIndex.internalPointer()))
item->setChecked(checkState);
}
emit dataChanged(currentRootIndex, last);
}
}
} // namespace Internal } // namespace Internal
} // namespace Autotest } // namespace Autotest

View File

@@ -45,7 +45,6 @@ public:
void deselectAll(); void deselectAll();
private: private:
void changeCheckStateAll(const Qt::CheckState checkState);
Core::IContext *m_context; Core::IContext *m_context;
}; };

View File

@@ -368,26 +368,23 @@ QFuture<CppTools::CursorInfo> BackendCommunicator::requestReferences(
const FileContainer &fileContainer, const FileContainer &fileContainer,
quint32 line, quint32 line,
quint32 column, quint32 column,
QTextDocument *textDocument,
const CppTools::SemanticInfo::LocalUseMap &localUses) const CppTools::SemanticInfo::LocalUseMap &localUses)
{ {
const RequestReferencesMessage message(fileContainer, line, column); const RequestReferencesMessage message(fileContainer, line, column);
m_sender->requestReferences(message); m_sender->requestReferences(message);
return m_receiver.addExpectedReferencesMessage(message.ticketNumber(), textDocument, return m_receiver.addExpectedReferencesMessage(message.ticketNumber(), localUses);
localUses);
} }
QFuture<CppTools::CursorInfo> BackendCommunicator::requestLocalReferences( QFuture<CppTools::CursorInfo> BackendCommunicator::requestLocalReferences(
const FileContainer &fileContainer, const FileContainer &fileContainer,
quint32 line, quint32 line,
quint32 column, quint32 column)
QTextDocument *textDocument)
{ {
const RequestReferencesMessage message(fileContainer, line, column, true); const RequestReferencesMessage message(fileContainer, line, column, true);
m_sender->requestReferences(message); m_sender->requestReferences(message);
return m_receiver.addExpectedReferencesMessage(message.ticketNumber(), textDocument); return m_receiver.addExpectedReferencesMessage(message.ticketNumber());
} }
QFuture<CppTools::ToolTipInfo> BackendCommunicator::requestToolTip( QFuture<CppTools::ToolTipInfo> BackendCommunicator::requestToolTip(

View File

@@ -75,13 +75,11 @@ public:
const FileContainer &fileContainer, const FileContainer &fileContainer,
quint32 line, quint32 line,
quint32 column, quint32 column,
QTextDocument *textDocument,
const LocalUseMap &localUses); const LocalUseMap &localUses);
QFuture<CppTools::CursorInfo> requestLocalReferences( QFuture<CppTools::CursorInfo> requestLocalReferences(
const FileContainer &fileContainer, const FileContainer &fileContainer,
quint32 line, quint32 line,
quint32 column, quint32 column);
QTextDocument *textDocument);
QFuture<CppTools::ToolTipInfo> requestToolTip(const FileContainer &fileContainer, QFuture<CppTools::ToolTipInfo> requestToolTip(const FileContainer &fileContainer,
quint32 line, quint32 line,
quint32 column); quint32 column);

View File

@@ -101,16 +101,14 @@ void BackendReceiver::deleteProcessorsOfEditorWidget(TextEditor::TextEditorWidge
QFuture<CppTools::CursorInfo> BackendReceiver::addExpectedReferencesMessage( QFuture<CppTools::CursorInfo> BackendReceiver::addExpectedReferencesMessage(
quint64 ticket, quint64 ticket,
QTextDocument *textDocument,
const CppTools::SemanticInfo::LocalUseMap &localUses) const CppTools::SemanticInfo::LocalUseMap &localUses)
{ {
QTC_CHECK(textDocument);
QTC_CHECK(!m_referencesTable.contains(ticket)); QTC_CHECK(!m_referencesTable.contains(ticket));
QFutureInterface<CppTools::CursorInfo> futureInterface; QFutureInterface<CppTools::CursorInfo> futureInterface;
futureInterface.reportStarted(); futureInterface.reportStarted();
const ReferencesEntry entry{futureInterface, textDocument, localUses}; const ReferencesEntry entry{futureInterface, localUses};
m_referencesTable.insert(ticket, entry); m_referencesTable.insert(ticket, entry);
return futureInterface.future(); return futureInterface.future();
@@ -221,24 +219,17 @@ void BackendReceiver::documentAnnotationsChanged(const DocumentAnnotationsChange
} }
static static
CppTools::CursorInfo::Range toCursorInfoRange(const QTextDocument &textDocument, CppTools::CursorInfo::Range toCursorInfoRange(const SourceRangeContainer &sourceRange)
const SourceRangeContainer &sourceRange)
{ {
const SourceLocationContainer start = sourceRange.start(); const SourceLocationContainer start = sourceRange.start();
const SourceLocationContainer end = sourceRange.end(); const SourceLocationContainer end = sourceRange.end();
const unsigned length = end.column() - start.column(); const unsigned length = end.column() - start.column();
const QTextBlock block = textDocument.findBlockByNumber(static_cast<int>(start.line()) - 1); return CppTools::CursorInfo::Range(start.line(), start.column(), length);
const int shift = ClangCodeModel::Utils::extraUtf8CharsShift(block.text(),
static_cast<int>(start.column()));
const uint column = start.column() - static_cast<uint>(shift);
return CppTools::CursorInfo::Range(start.line(), column, length);
} }
static static
CppTools::CursorInfo toCursorInfo(const QTextDocument &textDocument, CppTools::CursorInfo toCursorInfo(const CppTools::SemanticInfo::LocalUseMap &localUses,
const CppTools::SemanticInfo::LocalUseMap &localUses,
const ReferencesMessage &message) const ReferencesMessage &message)
{ {
CppTools::CursorInfo result; CppTools::CursorInfo result;
@@ -246,7 +237,7 @@ CppTools::CursorInfo toCursorInfo(const QTextDocument &textDocument,
result.areUseRangesForLocalVariable = message.isLocalVariable(); result.areUseRangesForLocalVariable = message.isLocalVariable();
for (const SourceRangeContainer &reference : references) for (const SourceRangeContainer &reference : references)
result.useRanges.append(toCursorInfoRange(textDocument, reference)); result.useRanges.append(toCursorInfoRange(reference));
result.useRanges.reserve(references.size()); result.useRanges.reserve(references.size());
result.localUses = localUses; result.localUses = localUses;
@@ -284,8 +275,7 @@ void BackendReceiver::references(const ReferencesMessage &message)
if (futureInterface.isCanceled()) if (futureInterface.isCanceled())
return; // Editor document closed or a new request was issued making this result outdated. return; // Editor document closed or a new request was issued making this result outdated.
QTC_ASSERT(entry.textDocument, return); futureInterface.reportResult(toCursorInfo(entry.localUses, message));
futureInterface.reportResult(toCursorInfo(*entry.textDocument, entry.localUses, message));
futureInterface.reportFinished(); futureInterface.reportFinished();
} }

View File

@@ -56,7 +56,6 @@ public:
QFuture<CppTools::CursorInfo> QFuture<CppTools::CursorInfo>
addExpectedReferencesMessage(quint64 ticket, addExpectedReferencesMessage(quint64 ticket,
QTextDocument *textDocument,
const CppTools::SemanticInfo::LocalUseMap &localUses const CppTools::SemanticInfo::LocalUseMap &localUses
= CppTools::SemanticInfo::LocalUseMap()); = CppTools::SemanticInfo::LocalUseMap());
QFuture<CppTools::SymbolInfo> addExpectedRequestFollowSymbolMessage(quint64 ticket); QFuture<CppTools::SymbolInfo> addExpectedRequestFollowSymbolMessage(quint64 ticket);
@@ -82,13 +81,10 @@ private:
struct ReferencesEntry { struct ReferencesEntry {
ReferencesEntry() = default; ReferencesEntry() = default;
ReferencesEntry(QFutureInterface<CppTools::CursorInfo> futureInterface, ReferencesEntry(QFutureInterface<CppTools::CursorInfo> futureInterface,
QTextDocument *textDocument,
const CppTools::SemanticInfo::LocalUseMap &localUses) const CppTools::SemanticInfo::LocalUseMap &localUses)
: futureInterface(futureInterface) : futureInterface(futureInterface)
, textDocument(textDocument)
, localUses(localUses) {} , localUses(localUses) {}
QFutureInterface<CppTools::CursorInfo> futureInterface; QFutureInterface<CppTools::CursorInfo> futureInterface;
QPointer<QTextDocument> textDocument;
CppTools::SemanticInfo::LocalUseMap localUses; CppTools::SemanticInfo::LocalUseMap localUses;
}; };
QHash<quint64, ReferencesEntry> m_referencesTable; QHash<quint64, ReferencesEntry> m_referencesTable;

View File

@@ -559,7 +559,8 @@ ClangCompletionAssistProcessor::extractLineColumn(int position)
int line = -1, column = -1; int line = -1, column = -1;
::Utils::Text::convertPosition(m_interface->textDocument(), position, &line, &column); ::Utils::Text::convertPosition(m_interface->textDocument(), position, &line, &column);
const QTextBlock block = m_interface->textDocument()->findBlock(position); 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}; return {line, column};
} }

View File

@@ -64,8 +64,7 @@ int positionInText(QTextDocument *textDocument,
{ {
auto textBlock = textDocument->findBlockByNumber( auto textBlock = textDocument->findBlockByNumber(
static_cast<int>(sourceLocationContainer.line()) - 1); static_cast<int>(sourceLocationContainer.line()) - 1);
int column = static_cast<int>(sourceLocationContainer.column()) - 1; const int column = static_cast<int>(sourceLocationContainer.column()) - 1;
column -= ClangCodeModel::Utils::extraUtf8CharsShift(textBlock.text(), column);
return textBlock.position() + column; return textBlock.position() + column;
} }

View File

@@ -29,6 +29,7 @@
#include "clangdiagnostictooltipwidget.h" #include "clangdiagnostictooltipwidget.h"
#include "clangfixitoperation.h" #include "clangfixitoperation.h"
#include "clangfixitoperationsextractor.h" #include "clangfixitoperationsextractor.h"
#include "clangmodelmanagersupport.h"
#include "clangtokeninfosreporter.h" #include "clangtokeninfosreporter.h"
#include "clangprojectsettings.h" #include "clangprojectsettings.h"
#include "clangutils.h" #include "clangutils.h"
@@ -66,6 +67,12 @@
namespace ClangCodeModel { namespace ClangCodeModel {
namespace Internal { namespace Internal {
static ClangProjectSettings &getProjectSettings(ProjectExplorer::Project *project)
{
QTC_CHECK(project);
return ModelManagerSupportClang::instance()->projectSettings(project);
}
ClangEditorDocumentProcessor::ClangEditorDocumentProcessor( ClangEditorDocumentProcessor::ClangEditorDocumentProcessor(
BackendCommunicator &communicator, BackendCommunicator &communicator,
TextEditor::TextDocument *document) TextEditor::TextDocument *document)
@@ -174,6 +181,11 @@ void ClangEditorDocumentProcessor::clearProjectPart()
m_projectPart.clear(); m_projectPart.clear();
} }
Core::Id ClangEditorDocumentProcessor::diagnosticConfigId() const
{
return m_diagnosticConfigId;
}
void ClangEditorDocumentProcessor::updateCodeWarnings( void ClangEditorDocumentProcessor::updateCodeWarnings(
const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics, const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics,
const ClangBackEnd::DiagnosticContainer &firstHeaderErrorDiagnostic, const ClangBackEnd::DiagnosticContainer &firstHeaderErrorDiagnostic,
@@ -331,20 +343,19 @@ ClangEditorDocumentProcessor::cursorInfo(const CppTools::CursorInfoParams &param
{ {
int line, column; int line, column;
convertPosition(params.textCursor, &line, &column); convertPosition(params.textCursor, &line, &column);
++column; // for 1-based columns
if (!isCursorOnIdentifier(params.textCursor)) if (!isCursorOnIdentifier(params.textCursor))
return defaultCursorInfoFuture(); return defaultCursorInfoFuture();
const QTextBlock block = params.textCursor.document()->findBlockByNumber(line - 1); 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 const CppTools::SemanticInfo::LocalUseMap localUses
= CppTools::BuiltinCursorInfo::findLocalUses(params.semanticInfo.doc, line, column); = CppTools::BuiltinCursorInfo::findLocalUses(params.semanticInfo.doc, line, column);
return m_communicator.requestReferences(simpleFileContainer(), return m_communicator.requestReferences(simpleFileContainer(),
static_cast<quint32>(line), static_cast<quint32>(line),
static_cast<quint32>(column), static_cast<quint32>(column),
textDocument(),
localUses); localUses);
} }
@@ -361,8 +372,7 @@ QFuture<CppTools::CursorInfo> ClangEditorDocumentProcessor::requestLocalReferenc
return m_communicator.requestLocalReferences(simpleFileContainer(), return m_communicator.requestLocalReferences(simpleFileContainer(),
static_cast<quint32>(line), static_cast<quint32>(line),
static_cast<quint32>(column), static_cast<quint32>(column));
textDocument());
} }
QFuture<CppTools::SymbolInfo> QFuture<CppTools::SymbolInfo>
@@ -437,6 +447,7 @@ public:
} }
const QStringList &options() const { return m_options; } const QStringList &options() const { return m_options; }
const Core::Id &diagnosticConfigId() const { return m_diagnosticConfigId; }
private: private:
void addLanguageOptions() void addLanguageOptions()
@@ -458,21 +469,28 @@ private:
void addDiagnosticOptions() void addDiagnosticOptions()
{ {
if (m_projectPart.project) { if (m_projectPart.project) {
ClangProjectSettings projectSettings(m_projectPart.project); ClangProjectSettings &projectSettings = getProjectSettings(m_projectPart.project);
if (!projectSettings.useGlobalConfig()) { if (!projectSettings.useGlobalConfig()) {
const Core::Id warningConfigId = projectSettings.warningConfigId(); const Core::Id warningConfigId = projectSettings.warningConfigId();
const CppTools::ClangDiagnosticConfigsModel configsModel( const CppTools::ClangDiagnosticConfigsModel configsModel(
CppTools::codeModelSettings()->clangCustomDiagnosticConfigs()); CppTools::codeModelSettings()->clangCustomDiagnosticConfigs());
if (configsModel.hasConfigWithId(warningConfigId)) { if (configsModel.hasConfigWithId(warningConfigId)) {
m_options.append( addDiagnosticOptionsForConfig(configsModel.configWithId(warningConfigId));
configsModel.configWithId(warningConfigId).commandLineWarnings());
return; return;
} }
} }
} }
m_options.append( addDiagnosticOptionsForConfig(CppTools::codeModelSettings()->clangDiagnosticConfig());
CppTools::codeModelSettings()->clangDiagnosticConfig().commandLineWarnings()); }
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()) 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 (checks.isEmpty())
if (tidyChecks.isEmpty())
return; return;
addXclangArg("-add-plugin", "clang-tidy"); 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 (checks.isEmpty())
if (clazyChecks.isEmpty())
return; return;
addXclangArg("-add-plugin", "clang-lazy"); 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 // 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 // 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) if (!m_projectPart.project)
m_options.append(ClangProjectSettings::globalCommandLineOptions()); m_options.append(ClangProjectSettings::globalCommandLineOptions());
else else
m_options.append(ClangProjectSettings{m_projectPart.project}.commandLineOptions()); m_options.append(getProjectSettings(m_projectPart.project).commandLineOptions());
addTidyOptions();
addClazyOptions();
} }
void addPrecompiledHeaderOptions() void addPrecompiledHeaderOptions()
@@ -541,6 +554,7 @@ private:
const QString &m_filePath; const QString &m_filePath;
const CppTools::ProjectPart &m_projectPart; const CppTools::ProjectPart &m_projectPart;
Core::Id m_diagnosticConfigId;
QStringList m_options; QStringList m_options;
}; };
} // namespace } // namespace
@@ -563,6 +577,7 @@ void ClangEditorDocumentProcessor::registerTranslationUnitForEditor(
} }
const FileOptionsBuilder fileOptions(filePath(), projectPart); const FileOptionsBuilder fileOptions(filePath(), projectPart);
m_diagnosticConfigId = fileOptions.diagnosticConfigId();
m_communicator.registerTranslationUnitsForEditor( m_communicator.registerTranslationUnitsForEditor(
{fileContainerWithOptionsAndDocumentContent(projectPart, fileOptions.options())}); {fileContainerWithOptionsAndDocumentContent(projectPart, fileOptions.options())});
ClangCodeModel::Utils::setLastSentDocumentRevision(filePath(), revision()); ClangCodeModel::Utils::setLastSentDocumentRevision(filePath(), revision());

View File

@@ -28,6 +28,7 @@
#include "clangdiagnosticmanager.h" #include "clangdiagnosticmanager.h"
#include "clangeditordocumentparser.h" #include "clangeditordocumentparser.h"
#include <coreplugin/id.h>
#include <cpptools/builtineditordocumentprocessor.h> #include <cpptools/builtineditordocumentprocessor.h>
#include <cpptools/semantichighlighter.h> #include <cpptools/semantichighlighter.h>
@@ -67,6 +68,8 @@ public:
CppTools::ProjectPart::Ptr projectPart() const; CppTools::ProjectPart::Ptr projectPart() const;
void clearProjectPart(); void clearProjectPart();
Core::Id diagnosticConfigId() const;
void updateCodeWarnings(const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics, void updateCodeWarnings(const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics,
const ClangBackEnd::DiagnosticContainer &firstHeaderErrorDiagnostic, const ClangBackEnd::DiagnosticContainer &firstHeaderErrorDiagnostic,
uint documentRevision); uint documentRevision);
@@ -120,6 +123,7 @@ private:
BackendCommunicator &m_communicator; BackendCommunicator &m_communicator;
QSharedPointer<ClangEditorDocumentParser> m_parser; QSharedPointer<ClangEditorDocumentParser> m_parser;
CppTools::ProjectPart::Ptr m_projectPart; CppTools::ProjectPart::Ptr m_projectPart;
Core::Id m_diagnosticConfigId;
bool m_isProjectFile = false; bool m_isProjectFile = false;
QFutureWatcher<void> m_parserWatcher; QFutureWatcher<void> m_parserWatcher;
QTimer m_updateTranslationUnitTimer; QTimer m_updateTranslationUnitTimer;

View File

@@ -133,7 +133,10 @@ void ClangHoverHandler::identifyMatch(TextEditorWidget *editorWidget,
m_reportPriority = report; m_reportPriority = report;
m_futureWatcher.reset(new QFutureWatcher<CppTools::ToolTipInfo>()); m_futureWatcher.reset(new QFutureWatcher<CppTools::ToolTipInfo>());
QObject::connect(m_futureWatcher.data(), &QFutureWatcherBase::finished, [this]() { 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); m_futureWatcher->setFuture(future);
return; return;

View File

@@ -30,22 +30,27 @@
#include "clangutils.h" #include "clangutils.h"
#include "clangfollowsymbol.h" #include "clangfollowsymbol.h"
#include "clanghoverhandler.h" #include "clanghoverhandler.h"
#include "clangprojectsettings.h"
#include "clangrefactoringengine.h" #include "clangrefactoringengine.h"
#include "clangcurrentdocumentfilter.h" #include "clangcurrentdocumentfilter.h"
#include <coreplugin/editormanager/editormanager.h> #include <coreplugin/editormanager/editormanager.h>
#include <cpptools/cppcodemodelsettings.h>
#include <cpptools/cppfollowsymbolundercursor.h> #include <cpptools/cppfollowsymbolundercursor.h>
#include <cpptools/cppmodelmanager.h> #include <cpptools/cppmodelmanager.h>
#include <cpptools/cpptoolsreuse.h>
#include <cpptools/editordocumenthandle.h> #include <cpptools/editordocumenthandle.h>
#include <cpptools/projectinfo.h> #include <cpptools/projectinfo.h>
#include <texteditor/quickfix.h> #include <texteditor/quickfix.h>
#include <projectexplorer/project.h> #include <projectexplorer/project.h>
#include <projectexplorer/session.h>
#include <clangsupport/cmbregisterprojectsforeditormessage.h> #include <clangsupport/cmbregisterprojectsforeditormessage.h>
#include <clangsupport/filecontainer.h> #include <clangsupport/filecontainer.h>
#include <clangsupport/projectpartcontainer.h> #include <clangsupport/projectpartcontainer.h>
#include <utils/algorithm.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <QCoreApplication> #include <QCoreApplication>
@@ -100,11 +105,22 @@ ModelManagerSupportClang::ModelManagerSupportClang()
connect(modelManager, &CppTools::CppModelManager::projectPartsRemoved, connect(modelManager, &CppTools::CppModelManager::projectPartsRemoved,
this, &ModelManagerSupportClang::onProjectPartsRemoved); 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(); m_communicator.registerFallbackProjectPart();
} }
ModelManagerSupportClang::~ModelManagerSupportClang() ModelManagerSupportClang::~ModelManagerSupportClang()
{ {
QTC_CHECK(m_projectSettings.isEmpty());
m_instance = 0; m_instance = 0;
} }
@@ -336,6 +352,52 @@ void ModelManagerSupportClang::onTextMarkContextMenuRequested(TextEditor::TextEd
} }
} }
using ClangEditorDocumentProcessors = QVector<ClangEditorDocumentProcessor *>;
static ClangEditorDocumentProcessors clangProcessors()
{
ClangEditorDocumentProcessors result;
foreach (auto *editorDocument, cppModelManager()->cppEditorDocuments())
result.append(qobject_cast<ClangEditorDocumentProcessor *>(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) void ModelManagerSupportClang::onProjectPartsUpdated(ProjectExplorer::Project *project)
{ {
QTC_ASSERT(project, return); QTC_ASSERT(project, return);
@@ -355,21 +417,25 @@ void ModelManagerSupportClang::onProjectPartsRemoved(const QStringList &projectP
} }
} }
static QVector<ClangEditorDocumentProcessor *> static ClangEditorDocumentProcessors clangProcessorsWithDiagnosticConfig(
const QVector<Core::Id> &configIds)
{
return ::Utils::filtered(clangProcessors(), [configIds](ClangEditorDocumentProcessor *p) {
return configIds.contains(p->diagnosticConfigId());
});
}
void ModelManagerSupportClang::onDiagnosticConfigsInvalidated(const QVector<Core::Id> &configIds)
{
updateProcessors(clangProcessorsWithDiagnosticConfig(configIds));
}
static ClangEditorDocumentProcessors
clangProcessorsWithProjectParts(const QStringList &projectPartIds) clangProcessorsWithProjectParts(const QStringList &projectPartIds)
{ {
QVector<ClangEditorDocumentProcessor *> result; return ::Utils::filtered(clangProcessors(), [projectPartIds](ClangEditorDocumentProcessor *p) {
return p->hasProjectPart() && projectPartIds.contains(p->projectPart()->id());
foreach (auto *editorDocument, cppModelManager()->cppEditorDocuments()) { });
auto *processor = editorDocument->processor();
auto *clangProcessor = qobject_cast<ClangEditorDocumentProcessor *>(processor);
if (clangProcessor && clangProcessor->hasProjectPart()) {
if (projectPartIds.contains(clangProcessor->projectPart()->id()))
result.append(clangProcessor);
}
}
return result;
} }
void ModelManagerSupportClang::unregisterTranslationUnitsWithProjectParts( void ModelManagerSupportClang::unregisterTranslationUnitsWithProjectParts(
@@ -398,6 +464,12 @@ QString ModelManagerSupportClang::dummyUiHeaderOnDiskPath(const QString &filePat
return m_uiHeaderOnDiskManager.mapPath(filePath); return m_uiHeaderOnDiskManager.mapPath(filePath);
} }
ClangProjectSettings &ModelManagerSupportClang::projectSettings(
ProjectExplorer::Project *project) const
{
return *m_projectSettings.value(project);
}
QString ModelManagerSupportClang::dummyUiHeaderOnDiskDirPath() const QString ModelManagerSupportClang::dummyUiHeaderOnDiskDirPath() const
{ {
return m_uiHeaderOnDiskManager.directoryPath(); return m_uiHeaderOnDiskManager.directoryPath();

View File

@@ -40,7 +40,10 @@ class QMenu;
class QWidget; class QWidget;
QT_END_NAMESPACE QT_END_NAMESPACE
namespace Core { class IDocument; } namespace Core {
class IDocument;
class Id;
} // namespace Core
namespace TextEditor { class TextEditorWidget; } namespace TextEditor { class TextEditorWidget; }
namespace CppTools { namespace CppTools {
class FollowSymbolInterface; class FollowSymbolInterface;
@@ -50,6 +53,8 @@ class RefactoringEngineInterface;
namespace ClangCodeModel { namespace ClangCodeModel {
namespace Internal { namespace Internal {
class ClangProjectSettings;
class ModelManagerSupportClang: class ModelManagerSupportClang:
public QObject, public QObject,
public CppTools::ModelManagerSupport public CppTools::ModelManagerSupport
@@ -71,6 +76,8 @@ public:
QString dummyUiHeaderOnDiskDirPath() const; QString dummyUiHeaderOnDiskDirPath() const;
QString dummyUiHeaderOnDiskPath(const QString &filePath) const; QString dummyUiHeaderOnDiskPath(const QString &filePath) const;
ClangProjectSettings &projectSettings(ProjectExplorer::Project *project) const;
static ModelManagerSupportClang *instance(); static ModelManagerSupportClang *instance();
private: private:
@@ -93,9 +100,14 @@ private:
int lineNumber, int lineNumber,
QMenu *menu); QMenu *menu);
void onProjectAdded(ProjectExplorer::Project *project);
void onAboutToRemoveProject(ProjectExplorer::Project *project);
void onProjectPartsUpdated(ProjectExplorer::Project *project); void onProjectPartsUpdated(ProjectExplorer::Project *project);
void onProjectPartsRemoved(const QStringList &projectPartIds); void onProjectPartsRemoved(const QStringList &projectPartIds);
void onDiagnosticConfigsInvalidated(const QVector<Core::Id> &configIds);
void unregisterTranslationUnitsWithProjectParts(const QStringList &projectPartIds); void unregisterTranslationUnitsWithProjectParts(const QStringList &projectPartIds);
void connectTextDocumentToTranslationUnit(TextEditor::TextDocument *textDocument); void connectTextDocumentToTranslationUnit(TextEditor::TextDocument *textDocument);
@@ -111,6 +123,8 @@ private:
ClangCompletionAssistProvider m_completionAssistProvider; ClangCompletionAssistProvider m_completionAssistProvider;
std::unique_ptr<CppTools::FollowSymbolInterface> m_followSymbol; std::unique_ptr<CppTools::FollowSymbolInterface> m_followSymbol;
std::unique_ptr<CppTools::RefactoringEngineInterface> m_refactoringEngine; std::unique_ptr<CppTools::RefactoringEngineInterface> m_refactoringEngine;
QHash<ProjectExplorer::Project *, ClangProjectSettings *> m_projectSettings;
}; };
class ModelManagerSupportProviderClang : public CppTools::ModelManagerSupportProvider class ModelManagerSupportProviderClang : public CppTools::ModelManagerSupportProvider

View File

@@ -42,6 +42,25 @@ static QString warningConfigIdKey()
static QString customCommandLineKey() static QString customCommandLineKey()
{ return QLatin1String("ClangCodeModel.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) ClangProjectSettings::ClangProjectSettings(ProjectExplorer::Project *project)
: m_project(project) : m_project(project)
{ {
@@ -88,23 +107,27 @@ void ClangProjectSettings::setCommandLineOptions(const QStringList &options)
void ClangProjectSettings::load() void ClangProjectSettings::load()
{ {
const QVariant useGlobalConfigVariant = m_project->namedSettings(useGlobalConfigKey()); setUseGlobalConfig(useGlobalConfigFromSettings(m_project));
const bool useGlobalConfig = useGlobalConfigVariant.isValid() setWarningConfigId(warningConfigIdFromSettings(m_project));
? useGlobalConfigVariant.toBool() m_customCommandLineOptions = customCommandLineFromSettings(m_project);
: 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();
} }
void ClangProjectSettings::store() 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(useGlobalConfigKey(), useGlobalConfig());
m_project->setNamedSettings(warningConfigIdKey(), warningConfigId().toSetting()); m_project->setNamedSettings(warningConfigIdKey(), warningConfigId().toSetting());
m_project->setNamedSettings(customCommandLineKey(), m_customCommandLineOptions); m_project->setNamedSettings(customCommandLineKey(), m_customCommandLineOptions);
if (settingsChanged)
emit changed();
} }
QStringList ClangProjectSettings::globalCommandLineOptions() QStringList ClangProjectSettings::globalCommandLineOptions()

View File

@@ -59,6 +59,9 @@ public:
static QStringList globalCommandLineOptions(); static QStringList globalCommandLineOptions();
signals:
void changed();
private: private:
ProjectExplorer::Project *m_project; ProjectExplorer::Project *m_project;
bool m_useGlobalConfig = true; bool m_useGlobalConfig = true;

View File

@@ -25,6 +25,7 @@
#include "clangprojectsettingswidget.h" #include "clangprojectsettingswidget.h"
#include "clangmodelmanagersupport.h"
#include "clangprojectsettings.h" #include "clangprojectsettings.h"
#include <coreplugin/icore.h> #include <coreplugin/icore.h>
@@ -52,7 +53,7 @@ static Core::Id configIdForProject(ClangProjectSettings &projectSettings)
} }
ClangProjectSettingsWidget::ClangProjectSettingsWidget(ProjectExplorer::Project *project) ClangProjectSettingsWidget::ClangProjectSettingsWidget(ProjectExplorer::Project *project)
: m_projectSettings(project) : m_projectSettings(ModelManagerSupportClang::instance()->projectSettings(project))
{ {
m_ui.setupUi(this); m_ui.setupUi(this);
@@ -76,6 +77,8 @@ ClangProjectSettingsWidget::ClangProjectSettingsWidget(ProjectExplorer::Project
connect(m_ui.clangSettings, connect(m_ui.clangSettings,
static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
this, &ClangProjectSettingsWidget::onClangSettingsChanged); this, &ClangProjectSettingsWidget::onClangSettingsChanged);
connect(project, &ProjectExplorer::Project::aboutToSaveSettings,
this, &ClangProjectSettingsWidget::onAboutToSaveProjectSettings);
m_ui.diagnosticConfigurationGroupBox->layout()->addWidget(m_diagnosticConfigWidget); m_ui.diagnosticConfigurationGroupBox->layout()->addWidget(m_diagnosticConfigWidget);
} }
@@ -86,7 +89,6 @@ void ClangProjectSettingsWidget::onCurrentWarningConfigChanged(const Core::Id &c
if (m_projectSettings.useGlobalConfig()) if (m_projectSettings.useGlobalConfig())
return; return;
m_projectSettings.setWarningConfigId(currentConfigId); m_projectSettings.setWarningConfigId(currentConfigId);
m_projectSettings.store();
} }
void ClangProjectSettingsWidget::onCustomWarningConfigsChanged( void ClangProjectSettingsWidget::onCustomWarningConfigsChanged(
@@ -97,7 +99,6 @@ void ClangProjectSettingsWidget::onCustomWarningConfigsChanged(
const QSharedPointer<CppTools::CppCodeModelSettings> codeModelSettings const QSharedPointer<CppTools::CppCodeModelSettings> codeModelSettings
= CppTools::codeModelSettings(); = CppTools::codeModelSettings();
codeModelSettings->setClangCustomDiagnosticConfigs(customConfigs); codeModelSettings->setClangCustomDiagnosticConfigs(customConfigs);
codeModelSettings->toSettings(Core::ICore::settings());
connectToCppCodeModelSettingsChanged(); connectToCppCodeModelSettingsChanged();
} }
@@ -115,16 +116,19 @@ void ClangProjectSettingsWidget::onDelayedTemplateParseClicked(bool checked)
options.removeAll(QLatin1String{ClangProjectSettings::NoDelayedTemplateParsing}); options.removeAll(QLatin1String{ClangProjectSettings::NoDelayedTemplateParsing});
options.append(extraFlag); options.append(extraFlag);
m_projectSettings.setCommandLineOptions(options); m_projectSettings.setCommandLineOptions(options);
m_projectSettings.store();
} }
void ClangProjectSettingsWidget::onClangSettingsChanged(int index) void ClangProjectSettingsWidget::onClangSettingsChanged(int index)
{ {
m_projectSettings.setUseGlobalConfig(index == 0 ? true : false); m_projectSettings.setUseGlobalConfig(index == 0 ? true : false);
m_projectSettings.store();
syncOtherWidgetsToComboBox(); syncOtherWidgetsToComboBox();
} }
void ClangProjectSettingsWidget::onAboutToSaveProjectSettings()
{
CppTools::codeModelSettings()->toSettings(Core::ICore::settings());
}
void ClangProjectSettingsWidget::syncOtherWidgetsToComboBox() void ClangProjectSettingsWidget::syncOtherWidgetsToComboBox()
{ {
const QStringList options = m_projectSettings.commandLineOptions(); const QStringList options = m_projectSettings.commandLineOptions();

View File

@@ -51,6 +51,7 @@ private:
void onCustomWarningConfigsChanged(const CppTools::ClangDiagnosticConfigs &customConfigs); void onCustomWarningConfigsChanged(const CppTools::ClangDiagnosticConfigs &customConfigs);
void onDelayedTemplateParseClicked(bool); void onDelayedTemplateParseClicked(bool);
void onClangSettingsChanged(int index); void onClangSettingsChanged(int index);
void onAboutToSaveProjectSettings();
void refreshDiagnosticConfigsWidgetFromSettings(); void refreshDiagnosticConfigsWidgetFromSettings();
void connectToCppCodeModelSettingsChanged(); void connectToCppCodeModelSettingsChanged();
void disconnectFromCppCodeModelSettingsChanged(); void disconnectFromCppCodeModelSettingsChanged();
@@ -58,7 +59,7 @@ private:
private: private:
Ui::ClangProjectSettingsWidget m_ui; Ui::ClangProjectSettingsWidget m_ui;
ClangProjectSettings m_projectSettings; ClangProjectSettings &m_projectSettings;
QPointer<CppTools::ClangDiagnosticConfigsWidget> m_diagnosticConfigWidget; QPointer<CppTools::ClangDiagnosticConfigsWidget> m_diagnosticConfigWidget;
}; };

View File

@@ -190,31 +190,5 @@ void setLastSentDocumentRevision(const QString &filePath, uint revision)
document->sendTracker().setLastSentRevision(int(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<uchar>(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 Utils
} // namespace Clang } // namespace Clang

View File

@@ -47,7 +47,5 @@ CppTools::ProjectPart::Ptr projectPartForFileBasedOnProcessor(const QString &fil
bool isProjectPartLoaded(const CppTools::ProjectPart::Ptr projectPart); bool isProjectPartLoaded(const CppTools::ProjectPart::Ptr projectPart);
QString projectPartIdForFile(const QString &filePath); QString projectPartIdForFile(const QString &filePath);
int extraUtf8CharsShift(const QString &str, int column);
} // namespace Utils } // namespace Utils
} // namespace Clang } // namespace Clang

View File

@@ -460,7 +460,6 @@ int ServerModeReader::calculateProgress(const int minRange, const int min, const
void ServerModeReader::extractCodeModelData(const QVariantMap &data) void ServerModeReader::extractCodeModelData(const QVariantMap &data)
{ {
const QVariantList configs = data.value("configurations").toList(); const QVariantList configs = data.value("configurations").toList();
QTC_CHECK(configs.count() == 1); // FIXME: Support several configurations!
for (const QVariant &c : configs) { for (const QVariant &c : configs) {
const QVariantMap &cData = c.toMap(); const QVariantMap &cData = c.toMap();
extractConfigurationData(cData); extractConfigurationData(cData);
@@ -842,6 +841,11 @@ void ServerModeReader::addFileGroups(ProjectNode *targetRoot,
{ {
QList<FileNode *> toList; QList<FileNode *> toList;
QSet<Utils::FileName> alreadyListed; QSet<Utils::FileName> alreadyListed;
// Files already added by other configurations:
targetRoot->forEachGenericNode([&alreadyListed](const Node *n) {
alreadyListed.insert(n->filePath());
});
for (const FileGroup *f : fileGroups) { for (const FileGroup *f : fileGroups) {
const QList<FileName> newSources = Utils::filtered(f->sources, [&alreadyListed](const Utils::FileName &fn) { const QList<FileName> newSources = Utils::filtered(f->sources, [&alreadyListed](const Utils::FileName &fn) {
const int count = alreadyListed.count(); const int count = alreadyListed.count();

View File

@@ -93,6 +93,8 @@ public:
virtual QFuture<SymbolInfo> requestFollowSymbol(int line, int column) = 0; virtual QFuture<SymbolInfo> requestFollowSymbol(int line, int column) = 0;
virtual QFuture<ToolTipInfo> toolTipInfo(const QByteArray &codecName, int line, int column); virtual QFuture<ToolTipInfo> toolTipInfo(const QByteArray &codecName, int line, int column);
QString filePath() const { return m_filePath; }
public: public:
using HeaderErrorDiagnosticWidgetCreator = std::function<QWidget*()>; using HeaderErrorDiagnosticWidgetCreator = std::function<QWidget*()>;
@@ -117,7 +119,6 @@ protected:
BaseEditorDocumentParser::UpdateParams updateParams); BaseEditorDocumentParser::UpdateParams updateParams);
// Convenience // Convenience
QString filePath() const { return m_filePath; }
unsigned revision() const { return static_cast<unsigned>(m_textDocument->revision()); } unsigned revision() const { return static_cast<unsigned>(m_textDocument->revision()); }
QTextDocument *textDocument() const { return m_textDocument; } QTextDocument *textDocument() const { return m_textDocument; }

View File

@@ -47,14 +47,14 @@ void ClangDiagnosticConfig::setDisplayName(const QString &displayName)
m_displayName = 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 bool ClangDiagnosticConfig::isReadOnly() const
@@ -71,8 +71,35 @@ bool ClangDiagnosticConfig::operator==(const ClangDiagnosticConfig &other) const
{ {
return m_id == other.m_id return m_id == other.m_id
&& m_displayName == other.m_displayName && 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; && 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 } // namespace CppTools

View File

@@ -43,18 +43,27 @@ public:
QString displayName() const; QString displayName() const;
void setDisplayName(const QString &displayName); void setDisplayName(const QString &displayName);
QStringList commandLineWarnings() const; QStringList clangOptions() const;
void setCommandLineWarnings(const QStringList &commandLineWarnings); void setClangOptions(const QStringList &options);
QString clangTidyChecks() const;
void setClangTidyChecks(const QString &checks);
QString clazyChecks() const;
void setClazyChecks(const QString &checks);
bool isReadOnly() const; bool isReadOnly() const;
void setIsReadOnly(bool isReadOnly); void setIsReadOnly(bool isReadOnly);
bool operator==(const ClangDiagnosticConfig &other) const; bool operator==(const ClangDiagnosticConfig &other) const;
bool operator!=(const ClangDiagnosticConfig &other) const;
private: private:
Core::Id m_id; Core::Id m_id;
QString m_displayName; QString m_displayName;
QStringList m_commandLineWarnings; QStringList m_clangOptions;
QString m_clangTidyChecks;
QString m_clazyChecks;
bool m_isReadOnly = false; bool m_isReadOnly = false;
}; };

View File

@@ -45,7 +45,7 @@ static void addConfigForQuestionableConstructs(ClangDiagnosticConfigsModel &mode
config.setDisplayName(QCoreApplication::translate("ClangDiagnosticConfigsModel", config.setDisplayName(QCoreApplication::translate("ClangDiagnosticConfigsModel",
"Warnings for questionable constructs")); "Warnings for questionable constructs"));
config.setIsReadOnly(true); config.setIsReadOnly(true);
config.setCommandLineWarnings(QStringList{ config.setClangOptions(QStringList{
QStringLiteral("-Wall"), QStringLiteral("-Wall"),
QStringLiteral("-Wextra"), QStringLiteral("-Wextra"),
} + commonWarnings()); } + commonWarnings());
@@ -60,7 +60,7 @@ static void addConfigForPedanticWarnings(ClangDiagnosticConfigsModel &model)
config.setDisplayName(QCoreApplication::translate("ClangDiagnosticConfigsModel", config.setDisplayName(QCoreApplication::translate("ClangDiagnosticConfigsModel",
"Pedantic Warnings")); "Pedantic Warnings"));
config.setIsReadOnly(true); config.setIsReadOnly(true);
config.setCommandLineWarnings(QStringList{QStringLiteral("-Wpedantic")} + commonWarnings()); config.setClangOptions(QStringList{QStringLiteral("-Wpedantic")} + commonWarnings());
model.appendOrUpdate(config); model.appendOrUpdate(config);
} }
@@ -72,7 +72,7 @@ static void addConfigForAlmostEveryWarning(ClangDiagnosticConfigsModel &model)
config.setDisplayName(QCoreApplication::translate("ClangDiagnosticConfigsModel", config.setDisplayName(QCoreApplication::translate("ClangDiagnosticConfigsModel",
"Warnings for almost everything")); "Warnings for almost everything"));
config.setIsReadOnly(true); config.setIsReadOnly(true);
config.setCommandLineWarnings(QStringList{ config.setClangOptions(QStringList{
QStringLiteral("-Weverything"), QStringLiteral("-Weverything"),
QStringLiteral("-Wno-c++98-compat"), QStringLiteral("-Wno-c++98-compat"),
QStringLiteral("-Wno-c++98-compat-pedantic"), QStringLiteral("-Wno-c++98-compat-pedantic"),
@@ -158,6 +158,23 @@ ClangDiagnosticConfigsModel::displayNameWithBuiltinIndication(const ClangDiagnos
: config.displayName(); : config.displayName();
} }
QVector<Core::Id> ClangDiagnosticConfigsModel::changedOrRemovedConfigs(
const ClangDiagnosticConfigs &oldConfigs, const ClangDiagnosticConfigs &newConfigs)
{
ClangDiagnosticConfigsModel newConfigsModel(newConfigs);
QVector<Core::Id> 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 int ClangDiagnosticConfigsModel::indexOfConfig(const Core::Id &id) const
{ {
return Utils::indexOf(m_diagnosticConfigs, [&](const ClangDiagnosticConfig &config) { return Utils::indexOf(m_diagnosticConfigs, [&](const ClangDiagnosticConfig &config) {

View File

@@ -29,6 +29,8 @@
#include "clangdiagnosticconfig.h" #include "clangdiagnosticconfig.h"
#include <QVector>
namespace CppTools { namespace CppTools {
class CPPTOOLS_EXPORT ClangDiagnosticConfigsModel class CPPTOOLS_EXPORT ClangDiagnosticConfigsModel
@@ -47,11 +49,11 @@ public:
ClangDiagnosticConfigs configs() const; ClangDiagnosticConfigs configs() const;
bool hasConfigWithId(const Core::Id &id) const; bool hasConfigWithId(const Core::Id &id) const;
const ClangDiagnosticConfig &configWithId(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); static QString displayNameWithBuiltinIndication(const ClangDiagnosticConfig &config);
static QVector<Core::Id> changedOrRemovedConfigs(const ClangDiagnosticConfigs &oldConfigs,
private: const ClangDiagnosticConfigs &newConfigs);
int indexOfConfig(const Core::Id &id) const;
private: private:
ClangDiagnosticConfigs m_diagnosticConfigs; ClangDiagnosticConfigs m_diagnosticConfigs;

View File

@@ -25,6 +25,8 @@
#include "clangdiagnosticconfigswidget.h" #include "clangdiagnosticconfigswidget.h"
#include "ui_clangdiagnosticconfigswidget.h" #include "ui_clangdiagnosticconfigswidget.h"
#include "ui_clazychecks.h"
#include "ui_tidychecks.h"
#include <utils/algorithm.h> #include <utils/algorithm.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
@@ -45,6 +47,7 @@ ClangDiagnosticConfigsWidget::ClangDiagnosticConfigsWidget(
, m_diagnosticConfigsModel(diagnosticConfigsModel) , m_diagnosticConfigsModel(diagnosticConfigsModel)
{ {
m_ui->setupUi(this); m_ui->setupUi(this);
setupPluginsWidgets();
connectConfigChooserCurrentIndex(); connectConfigChooserCurrentIndex();
connect(m_ui->copyButton, &QPushButton::clicked, connect(m_ui->copyButton, &QPushButton::clicked,
@@ -108,6 +111,18 @@ void ClangDiagnosticConfigsWidget::onRemoveButtonClicked()
syncConfigChooserToModel(); 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) static bool isAcceptedWarningOption(const QString &option)
{ {
return option == "-w" return option == "-w"
@@ -162,10 +177,8 @@ void ClangDiagnosticConfigsWidget::onDiagnosticOptionsEdited()
// Commit valid changes // Commit valid changes
ClangDiagnosticConfig updatedConfig = currentConfig(); ClangDiagnosticConfig updatedConfig = currentConfig();
updatedConfig.setCommandLineWarnings(normalizedOptions); updatedConfig.setClangOptions(normalizedOptions);
updateConfig(updatedConfig);
m_diagnosticConfigsModel.appendOrUpdate(updatedConfig);
emit customConfigsChanged(customConfigs());
} }
void ClangDiagnosticConfigsWidget::syncWidgetsToModel(const Core::Id &configToSelect) void ClangDiagnosticConfigsWidget::syncWidgetsToModel(const Core::Id &configToSelect)
@@ -213,12 +226,74 @@ void ClangDiagnosticConfigsWidget::syncOtherWidgetsToComboBox()
// Update main button row // Update main button row
m_ui->removeButton->setEnabled(!config.isReadOnly()); m_ui->removeButton->setEnabled(!config.isReadOnly());
// Update child widgets // Update Text Edit
const QString options = m_notAcceptedOptions.contains(config.id()) const QString options = m_notAcceptedOptions.contains(config.id())
? m_notAcceptedOptions.value(config.id()) ? m_notAcceptedOptions.value(config.id())
: config.commandLineWarnings().join(QLatin1Char(' ')); : config.clangOptions().join(QLatin1Char(' '));
setDiagnosticOptions(options); setDiagnosticOptions(options);
m_ui->diagnosticOptionsTextEdit->setReadOnly(config.isReadOnly()); 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<unsigned>(index)]);
}
void ClangDiagnosticConfigsWidget::updateConfig(const ClangDiagnosticConfig &config)
{
m_diagnosticConfigsModel.appendOrUpdate(config);
emit customConfigsChanged(customConfigs());
} }
bool ClangDiagnosticConfigsWidget::isConfigChooserEmpty() const bool ClangDiagnosticConfigsWidget::isConfigChooserEmpty() const
@@ -264,6 +339,18 @@ void ClangDiagnosticConfigsWidget::updateValidityWidgets(const QString &errorMes
m_ui->validationResultLabel->setStyleSheet(styleSheet); 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() void ClangDiagnosticConfigsWidget::connectConfigChooserCurrentIndex()
{ {
connect(m_ui->configChooserComboBox, connect(m_ui->configChooserComboBox,
@@ -314,4 +401,31 @@ void ClangDiagnosticConfigsWidget::refresh(
syncWidgetsToModel(configToSelect); 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<void (QComboBox::*)(int index)>(&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 } // CppTools namespace

View File

@@ -33,9 +33,17 @@
#include <QHash> #include <QHash>
#include <QWidget> #include <QWidget>
#include <memory>
QT_FORWARD_DECLARE_CLASS(QListWidgetItem)
namespace CppTools { namespace CppTools {
namespace Ui { class ClangDiagnosticConfigsWidget; } namespace Ui {
class ClangDiagnosticConfigsWidget;
class ClazyChecks;
class TidyChecks;
}
class CPPTOOLS_EXPORT ClangDiagnosticConfigsWidget : public QWidget class CPPTOOLS_EXPORT ClangDiagnosticConfigsWidget : public QWidget
{ {
@@ -59,15 +67,23 @@ signals:
void customConfigsChanged(const CppTools::ClangDiagnosticConfigs &customConfigs); void customConfigsChanged(const CppTools::ClangDiagnosticConfigs &customConfigs);
private: private:
void setupPluginsWidgets();
void onCurrentConfigChanged(int); void onCurrentConfigChanged(int);
void onCopyButtonClicked(); void onCopyButtonClicked();
void onRemoveButtonClicked(); void onRemoveButtonClicked();
void onClangTidyItemChanged(QListWidgetItem *item);
void onDiagnosticOptionsEdited(); void onDiagnosticOptionsEdited();
void syncWidgetsToModel(const Core::Id &configToSelect = Core::Id()); void syncWidgetsToModel(const Core::Id &configToSelect = Core::Id());
void syncConfigChooserToModel(const Core::Id &configToSelect = Core::Id()); void syncConfigChooserToModel(const Core::Id &configToSelect = Core::Id());
void syncOtherWidgetsToComboBox(); 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; bool isConfigChooserEmpty() const;
const ClangDiagnosticConfig &currentConfig() const; const ClangDiagnosticConfig &currentConfig() const;
@@ -75,6 +91,9 @@ private:
void setDiagnosticOptions(const QString &options); void setDiagnosticOptions(const QString &options);
void updateValidityWidgets(const QString &errorMessage); void updateValidityWidgets(const QString &errorMessage);
void connectClangTidyItemChanged();
void disconnectClangTidyItemChanged();
void connectConfigChooserCurrentIndex(); void connectConfigChooserCurrentIndex();
void disconnectConfigChooserCurrentIndex(); void disconnectConfigChooserCurrentIndex();
void connectDiagnosticOptionsChanged(); void connectDiagnosticOptionsChanged();
@@ -84,6 +103,12 @@ private:
Ui::ClangDiagnosticConfigsWidget *m_ui; Ui::ClangDiagnosticConfigsWidget *m_ui;
ClangDiagnosticConfigsModel m_diagnosticConfigsModel; ClangDiagnosticConfigsModel m_diagnosticConfigsModel;
QHash<Core::Id, QString> m_notAcceptedOptions; QHash<Core::Id, QString> m_notAcceptedOptions;
std::unique_ptr<CppTools::Ui::ClazyChecks> m_clazyChecks;
QWidget *m_clazyChecksWidget = nullptr;
std::unique_ptr<CppTools::Ui::TidyChecks> m_tidyChecks;
QWidget *m_tidyChecksWidget = nullptr;
}; };
} // CppTools namespace } // CppTools namespace

View File

@@ -93,6 +93,9 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QTabWidget" name="pluginChecksTabs"/>
</item>
</layout> </layout>
</widget> </widget>
<customwidgets> <customwidgets>

View File

@@ -27,8 +27,10 @@
#include <coreplugin/icore.h> #include <coreplugin/icore.h>
#include <projectexplorer/project.h>
#include <projectexplorer/projectexplorerconstants.h> #include <projectexplorer/projectexplorerconstants.h>
#include <utils/fileutils.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <utils/qtcfallthrough.h> #include <utils/qtcfallthrough.h>
@@ -37,6 +39,8 @@
namespace CppTools { namespace CppTools {
static constexpr char SYSTEM_INCLUDE_PREFIX[] = "-isystem";
CompilerOptionsBuilder::CompilerOptionsBuilder(const ProjectPart &projectPart, CompilerOptionsBuilder::CompilerOptionsBuilder(const ProjectPart &projectPart,
const QString &clangVersion, const QString &clangVersion,
const QString &clangResourceDirectory) const QString &clangResourceDirectory)
@@ -119,10 +123,23 @@ void CompilerOptionsBuilder::enableExceptions()
add(QLatin1String("-fexceptions")); 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() void CompilerOptionsBuilder::addHeaderPathOptions()
{ {
typedef ProjectPartHeaderPath HeaderPath; typedef ProjectPartHeaderPath HeaderPath;
const QString defaultPrefix = includeDirOption(); const QString defaultPrefix = includeDirOption();
const Utils::FileName projectDirectory = projectTopLevelDirectory(m_projectPart);
QStringList result; QStringList result;
@@ -134,6 +151,7 @@ void CompilerOptionsBuilder::addHeaderPathOptions()
continue; continue;
QString prefix; QString prefix;
Utils::FileName path;
switch (headerPath.type) { switch (headerPath.type) {
case HeaderPath::FrameworkPath: case HeaderPath::FrameworkPath:
prefix = QLatin1String("-F"); prefix = QLatin1String("-F");
@@ -141,7 +159,11 @@ void CompilerOptionsBuilder::addHeaderPathOptions()
default: // This shouldn't happen, but let's be nice..: default: // This shouldn't happen, but let's be nice..:
// intentional fall-through: // intentional fall-through:
case HeaderPath::IncludePath: case HeaderPath::IncludePath:
prefix = defaultPrefix; path = absoluteDirectory(headerPath.path);
if (path == projectDirectory || path.isChildOf(projectDirectory))
prefix = defaultPrefix;
else
prefix = SYSTEM_INCLUDE_PREFIX;
break; break;
} }
@@ -409,7 +431,7 @@ void CompilerOptionsBuilder::addDefineFunctionMacrosMsvc()
QString CompilerOptionsBuilder::includeDirOption() const QString CompilerOptionsBuilder::includeDirOption() const
{ {
return QLatin1String("-isystem"); return QLatin1String("-I");
} }
QByteArray CompilerOptionsBuilder::macroOption(const ProjectExplorer::Macro &macro) const QByteArray CompilerOptionsBuilder::macroOption(const ProjectExplorer::Macro &macro) const
@@ -506,7 +528,7 @@ void CompilerOptionsBuilder::addPredefinedHeaderPathsOptions()
void CompilerOptionsBuilder::addClangIncludeFolder() void CompilerOptionsBuilder::addClangIncludeFolder()
{ {
QTC_CHECK(!m_clangVersion.isEmpty()); QTC_CHECK(!m_clangVersion.isEmpty());
add(includeDirOption()); add(SYSTEM_INCLUDE_PREFIX);
add(clangIncludeDirectory()); add(clangIncludeDirectory());
} }

View File

@@ -55,6 +55,12 @@ static QString clangDiagnosticConfigsArrayDisplayNameKey()
static QString clangDiagnosticConfigsArrayWarningsKey() static QString clangDiagnosticConfigsArrayWarningsKey()
{ return QLatin1String("diagnosticOptions"); } { return QLatin1String("diagnosticOptions"); }
static QString clangDiagnosticConfigsArrayClangTidyChecksKey()
{ return QLatin1String("clangTidyChecks"); }
static QString clangDiagnosticConfigsArrayClazyChecksKey()
{ return QLatin1String("clazyChecks"); }
static QString pchUsageKey() static QString pchUsageKey()
{ return QLatin1String(Constants::CPPTOOLS_MODEL_MANAGER_PCH_USAGE); } { return QLatin1String(Constants::CPPTOOLS_MODEL_MANAGER_PCH_USAGE); }
@@ -67,15 +73,12 @@ static QString skipIndexingBigFilesKey()
static QString indexerFileSizeLimitKey() static QString indexerFileSizeLimitKey()
{ return QLatin1String(Constants::CPPTOOLS_INDEXER_FILE_SIZE_LIMIT); } { return QLatin1String(Constants::CPPTOOLS_INDEXER_FILE_SIZE_LIMIT); }
static QString tidyChecksKey() static ClangDiagnosticConfigs customDiagnosticConfigsFromSettings(QSettings *s)
{ return QLatin1String(Constants::CPPTOOLS_TIDY_CHECKS); }
static QString clazyChecksKey()
{ return QLatin1String(Constants::CPPTOOLS_CLAZY_CHECKS); }
void CppCodeModelSettings::fromSettings(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()); const int size = s->beginReadArray(clangDiagnosticConfigsArrayKey());
for (int i = 0; i < size; ++i) { for (int i = 0; i < size; ++i) {
@@ -84,15 +87,30 @@ void CppCodeModelSettings::fromSettings(QSettings *s)
ClangDiagnosticConfig config; ClangDiagnosticConfig config;
config.setId(Core::Id::fromSetting(s->value(clangDiagnosticConfigsArrayIdKey()))); config.setId(Core::Id::fromSetting(s->value(clangDiagnosticConfigsArrayIdKey())));
config.setDisplayName(s->value(clangDiagnosticConfigsArrayDisplayNameKey()).toString()); config.setDisplayName(s->value(clangDiagnosticConfigsArrayDisplayNameKey()).toString());
config.setCommandLineWarnings(s->value(clangDiagnosticConfigsArrayWarningsKey()).toStringList()); config.setClangOptions(s->value(clangDiagnosticConfigsArrayWarningsKey()).toStringList());
m_clangCustomDiagnosticConfigs.append(config); config.setClangTidyChecks(s->value(clangDiagnosticConfigsArrayClangTidyChecksKey()).toString());
config.setClazyChecks(s->value(clangDiagnosticConfigsArrayClazyChecksKey()).toString());
configs.append(config);
} }
s->endArray(); s->endArray();
const Core::Id diagnosticConfigId = Core::Id::fromSetting( return configs;
s->value(clangDiagnosticConfigKey(), }
initialClangDiagnosticConfigId().toSetting()));
setClangDiagnosticConfigId(diagnosticConfigId); 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()); const QVariant pchUsageVariant = s->value(pchUsageKey(), initialPchUsage());
setPCHUsage(static_cast<PCHUsage>(pchUsageVariant.toInt())); setPCHUsage(static_cast<PCHUsage>(pchUsageVariant.toInt()));
@@ -107,11 +125,6 @@ void CppCodeModelSettings::fromSettings(QSettings *s)
const QVariant indexerFileSizeLimit = s->value(indexerFileSizeLimitKey(), 5); const QVariant indexerFileSizeLimit = s->value(indexerFileSizeLimitKey(), 5);
setIndexerFileSizeLimitInMb(indexerFileSizeLimit.toInt()); 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(); s->endGroup();
emit changed(); emit changed();
@@ -120,6 +133,8 @@ void CppCodeModelSettings::fromSettings(QSettings *s)
void CppCodeModelSettings::toSettings(QSettings *s) void CppCodeModelSettings::toSettings(QSettings *s)
{ {
s->beginGroup(QLatin1String(Constants::CPPTOOLS_SETTINGSGROUP)); s->beginGroup(QLatin1String(Constants::CPPTOOLS_SETTINGSGROUP));
const ClangDiagnosticConfigs previousConfigs = customDiagnosticConfigsFromSettings(s);
const Core::Id previousConfigId = clangDiagnosticConfigIdFromSettings(s);
s->beginWriteArray(clangDiagnosticConfigsArrayKey()); s->beginWriteArray(clangDiagnosticConfigsArrayKey());
for (int i = 0, size = m_clangCustomDiagnosticConfigs.size(); i < size; ++i) { for (int i = 0, size = m_clangCustomDiagnosticConfigs.size(); i < size; ++i) {
@@ -128,7 +143,9 @@ void CppCodeModelSettings::toSettings(QSettings *s)
s->setArrayIndex(i); s->setArrayIndex(i);
s->setValue(clangDiagnosticConfigsArrayIdKey(), config.id().toSetting()); s->setValue(clangDiagnosticConfigsArrayIdKey(), config.id().toSetting());
s->setValue(clangDiagnosticConfigsArrayDisplayNameKey(), config.displayName()); 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(); s->endArray();
@@ -138,11 +155,18 @@ void CppCodeModelSettings::toSettings(QSettings *s)
s->setValue(interpretAmbiguousHeadersAsCHeadersKey(), interpretAmbigiousHeadersAsCHeaders()); s->setValue(interpretAmbiguousHeadersAsCHeadersKey(), interpretAmbigiousHeadersAsCHeaders());
s->setValue(skipIndexingBigFilesKey(), skipIndexingBigFiles()); s->setValue(skipIndexingBigFilesKey(), skipIndexingBigFiles());
s->setValue(indexerFileSizeLimitKey(), indexerFileSizeLimitInMb()); s->setValue(indexerFileSizeLimitKey(), indexerFileSizeLimitInMb());
s->setValue(tidyChecksKey(), tidyChecks());
s->setValue(clazyChecksKey(), clazyChecks());
s->endGroup(); s->endGroup();
QVector<Core::Id> invalidated
= ClangDiagnosticConfigsModel::changedOrRemovedConfigs(previousConfigs,
m_clangCustomDiagnosticConfigs);
if (previousConfigId != clangDiagnosticConfigId() && !invalidated.contains(previousConfigId))
invalidated.append(previousConfigId);
if (!invalidated.isEmpty())
emit clangDiagnosticConfigsInvalidated(invalidated);
emit changed(); emit changed();
} }
@@ -212,23 +236,3 @@ void CppCodeModelSettings::setIndexerFileSizeLimitInMb(int sizeInMB)
{ {
m_indexerFileSizeLimitInMB = 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;
}

View File

@@ -72,13 +72,8 @@ public:
int indexerFileSizeLimitInMb() const; int indexerFileSizeLimitInMb() const;
void setIndexerFileSizeLimitInMb(int sizeInMB); void setIndexerFileSizeLimitInMb(int sizeInMB);
QString tidyChecks() const;
void setTidyChecks(QString checks);
QString clazyChecks() const;
void setClazyChecks(QString checks);
signals: signals:
void clangDiagnosticConfigsInvalidated(const QVector<Core::Id> &configId);
void changed(); void changed();
private: private:
@@ -88,9 +83,6 @@ private:
int m_indexerFileSizeLimitInMB = 5; int m_indexerFileSizeLimitInMB = 5;
ClangDiagnosticConfigs m_clangCustomDiagnosticConfigs; ClangDiagnosticConfigs m_clangCustomDiagnosticConfigs;
Core::Id m_clangDiagnosticConfigId; Core::Id m_clangDiagnosticConfigId;
QString m_tidyChecks;
QString m_clazyChecks;
}; };
} // namespace CppTools } // namespace CppTools

View File

@@ -29,8 +29,6 @@
#include "cppmodelmanager.h" #include "cppmodelmanager.h"
#include "cpptoolsconstants.h" #include "cpptoolsconstants.h"
#include "ui_cppcodemodelsettingspage.h" #include "ui_cppcodemodelsettingspage.h"
#include "ui_clazychecks.h"
#include "ui_tidychecks.h"
#include <coreplugin/icore.h> #include <coreplugin/icore.h>
#include <utils/algorithm.h> #include <utils/algorithm.h>
@@ -86,79 +84,6 @@ void CppCodeModelSettingsWidget::setupClangCodeModelWidgets()
diagnosticConfigsModel, diagnosticConfigsModel,
m_settings->clangDiagnosticConfigId()); m_settings->clangDiagnosticConfigId());
m_ui->clangSettingsGroupBox->layout()->addWidget(m_clangDiagnosticConfigsWidget); 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<QString, 5> 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<unsigned>(m_clazyChecks->clazyLevel->currentIndex());
m_clazyChecks->levelDescription->setText(levelDescriptions[index]);
}
connect(m_clazyChecks->clazyLevel,
static_cast<void (QComboBox::*)(int index)>(&QComboBox::currentIndexChanged),
[this](int index) {
m_clazyChecks->levelDescription->setText(levelDescriptions[static_cast<unsigned>(index)]);
if (index == 0) {
m_currentClazyChecks.clear();
return;
}
m_currentClazyChecks = m_clazyChecks->clazyLevel->itemText(index);
});
} }
void CppCodeModelSettingsWidget::setupGeneralWidgets() void CppCodeModelSettingsWidget::setupGeneralWidgets()
@@ -192,16 +117,6 @@ bool CppCodeModelSettingsWidget::applyClangCodeModelWidgetsToSettings() const
settingsChanged = true; 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; return settingsChanged;
} }

View File

@@ -32,8 +32,6 @@
#include <QPointer> #include <QPointer>
#include <QWidget> #include <QWidget>
#include <memory>
QT_FORWARD_DECLARE_CLASS(QComboBox) QT_FORWARD_DECLARE_CLASS(QComboBox)
QT_FORWARD_DECLARE_CLASS(QSettings) QT_FORWARD_DECLARE_CLASS(QSettings)
@@ -41,11 +39,6 @@ namespace CppTools {
class ClangDiagnosticConfigsWidget; class ClangDiagnosticConfigsWidget;
namespace Ui {
class ClazyChecks;
class TidyChecks;
} // namespace Ui
namespace Internal { namespace Internal {
namespace Ui { class CppCodeModelSettingsPage; } namespace Ui { class CppCodeModelSettingsPage; }
@@ -64,9 +57,6 @@ public:
private: private:
void setupGeneralWidgets(); void setupGeneralWidgets();
void setupClangCodeModelWidgets(); void setupClangCodeModelWidgets();
void setupPluginsWidgets();
void setupTidyChecks();
void setupClazyChecks();
bool applyGeneralWidgetsToSettings() const; bool applyGeneralWidgetsToSettings() const;
bool applyClangCodeModelWidgetsToSettings() const; bool applyClangCodeModelWidgetsToSettings() const;
@@ -75,14 +65,6 @@ private:
Ui::CppCodeModelSettingsPage *m_ui = nullptr; Ui::CppCodeModelSettingsPage *m_ui = nullptr;
QPointer<ClangDiagnosticConfigsWidget> m_clangDiagnosticConfigsWidget; QPointer<ClangDiagnosticConfigsWidget> m_clangDiagnosticConfigsWidget;
QSharedPointer<CppCodeModelSettings> m_settings; QSharedPointer<CppCodeModelSettings> m_settings;
std::unique_ptr<CppTools::Ui::ClazyChecks> m_clazyChecks;
QWidget *m_clazyChecksWidget = nullptr;
QString m_currentClazyChecks;
std::unique_ptr<CppTools::Ui::TidyChecks> m_tidyChecks;
QWidget *m_tidyChecksWidget = nullptr;
QString m_currentTidyChecks;
}; };
class CppCodeModelSettingsPage: public Core::IOptionsPage class CppCodeModelSettingsPage: public Core::IOptionsPage

View File

@@ -114,18 +114,6 @@
<layout class="QVBoxLayout" name="verticalLayout_3"/> <layout class="QVBoxLayout" name="verticalLayout_3"/>
</widget> </widget>
</item> </item>
<item>
<widget class="QGroupBox" name="clangPlugins">
<property name="title">
<string>Clang Plugins</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QTabWidget" name="pluginChecks"/>
</item>
</layout>
</widget>
</item>
<item> <item>
<spacer name="verticalSpacer"> <spacer name="verticalSpacer">
<property name="orientation"> <property name="orientation">

View File

@@ -56,8 +56,6 @@ const char CPPTOOLS_INTERPRET_AMBIGIUOUS_HEADERS_AS_C_HEADERS[]
= "InterpretAmbiguousHeadersAsCHeaders"; = "InterpretAmbiguousHeadersAsCHeaders";
const char CPPTOOLS_SKIP_INDEXING_BIG_FILES[] = "SkipIndexingBigFiles"; const char CPPTOOLS_SKIP_INDEXING_BIG_FILES[] = "SkipIndexingBigFiles";
const char CPPTOOLS_INDEXER_FILE_SIZE_LIMIT[] = "IndexerFileSizeLimit"; 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[] const char CPP_CLANG_BUILTIN_CONFIG_ID_EVERYTHING_WITH_EXCEPTIONS[]
= "Builtin.EverythingWithExceptions"; = "Builtin.EverythingWithExceptions";

View File

@@ -530,7 +530,7 @@ DebuggerSettings::DebuggerSettings()
insertItem(UseToolTipsInBreakpointsView, item); insertItem(UseToolTipsInBreakpointsView, item);
item = new SavedAction(this); 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->setText(tr("Use Tooltips in Stack View when Debugging"));
item->setToolTip(tr("<p>Checking this will enable tooltips in the stack " item->setToolTip(tr("<p>Checking this will enable tooltips in the stack "
"view during debugging.")); "view during debugging."));

View File

@@ -365,7 +365,13 @@ void DebuggerRunTool::setBreakOnMain(bool on)
void DebuggerRunTool::setUseTerminal(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); d->terminalRunner = new TerminalRunner(this);
addStartDependency(d->terminalRunner); addStartDependency(d->terminalRunner);
} }
@@ -891,15 +897,6 @@ DebuggerRunTool::DebuggerRunTool(RunControl *runControl, Kit *kit, bool allowTer
m_engine = createPdbEngine(); 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 DebuggerEngine *DebuggerRunTool::activeEngine() const

View File

@@ -292,7 +292,6 @@ void LldbEngine::setupEngine()
.arg(bp.id().toString()).arg(bp.state())); .arg(bp.id().toString()).arg(bp.state()));
} }
} }
notifyEngineSetupOk();
} else { } else {
notifyEngineSetupFailed(); notifyEngineSetupFailed();
} }

View File

@@ -88,16 +88,9 @@ bool ModelEditorPlugin::initialize(const QStringList &arguments, QString *errorS
Q_UNUSED(errorString); Q_UNUSED(errorString);
d->modelsManager = new ModelsManager(this); d->modelsManager = new ModelsManager(this);
addAutoReleasedObject(d->modelsManager);
d->uiController = new UiController(this); d->uiController = new UiController(this);
addAutoReleasedObject(d->uiController);
d->modelFactory = new ModelEditorFactory(d->uiController, this); d->modelFactory = new ModelEditorFactory(d->uiController, this);
addAutoReleasedObject(d->modelFactory);
d->settingsController = new SettingsController(this); d->settingsController = new SettingsController(this);
addAutoReleasedObject(d->settingsController);
Core::JsExpander::registerQObjectForJs(QLatin1String("Modeling"), new JsExtension(this)); Core::JsExpander::registerQObjectForJs(QLatin1String("Modeling"), new JsExtension(this));

View File

@@ -63,11 +63,9 @@ AndroidQmakeBuildConfiguration::AndroidQmakeBuildConfiguration(Target *target)
: QmakeBuildConfiguration(target) : QmakeBuildConfiguration(target)
{ {
updateCacheAndEmitEnvironmentChanged(); updateCacheAndEmitEnvironmentChanged();
connect(target->project(), &Project::parsingFinished, this, [this] {
auto updateGradle = [this] { AndroidManager::updateGradleProperties(BuildConfiguration::target()); }; AndroidManager::updateGradleProperties(BuildConfiguration::target());
});
connect(target->project(), &Project::parsingFinished, this, updateGradle);
connect(this, &AndroidQmakeBuildConfiguration::enabledChanged, this, updateGradle);
} }
void AndroidQmakeBuildConfiguration::initialize(const BuildInfo *info) void AndroidQmakeBuildConfiguration::initialize(const BuildInfo *info)

View File

@@ -64,6 +64,8 @@ QWidget *ChangeStyleWidgetAction::createWidget(QWidget *parent)
QComboBox *comboBox = new QComboBox(parent); QComboBox *comboBox = new QComboBox(parent);
comboBox->setToolTip(tr(enabledTooltip)); comboBox->setToolTip(tr(enabledTooltip));
comboBox->addItem("Default"); comboBox->addItem("Default");
comboBox->addItem("Fusion");
comboBox->addItem("Imagine");
comboBox->addItem("Material"); comboBox->addItem("Material");
comboBox->addItem("Universal"); comboBox->addItem("Universal");
comboBox->setEditable(true); comboBox->setEditable(true);

View File

@@ -164,6 +164,8 @@ const int priorityGoIntoComponent = 40;
const int priorityGenericToolBar = 50; const int priorityGenericToolBar = 50;
const int priorityLast = 60; const int priorityLast = 60;
const char addImagesDisplayString[] = QT_TRANSLATE_NOOP("QmlDesignerAddResources", "Image Files");
} //ComponentCoreConstants } //ComponentCoreConstants
} //QmlDesigner } //QmlDesigner

View File

@@ -178,6 +178,16 @@ void DesignerActionManager::setupContext()
m_designerActionManagerView->setupContext(); m_designerActionManagerView->setupContext();
} }
QList<AddResourceHandler> DesignerActionManager::addResourceHandler() const
{
return m_addResourceHandler;
}
void DesignerActionManager::registerAddResourceHandler(const AddResourceHandler &handler)
{
m_addResourceHandler.append(handler);
}
class VisiblityModelNodeAction : public ModelNodeContextMenuAction class VisiblityModelNodeAction : public ModelNodeContextMenuAction
{ {
public: public:
@@ -359,7 +369,7 @@ bool selectionHasSameParentAndInBaseState(const SelectionContext &context)
bool isNotInLayout(const SelectionContext &context) bool isNotInLayout(const SelectionContext &context)
{ {
if (selectionNotEmpty(context)) { if (selectionNotEmpty(context)) {
const ModelNode &selectedModelNode = context.selectedModelNodes().constFirst(); const ModelNode selectedModelNode = context.selectedModelNodes().constFirst();
ModelNode parentModelNode; ModelNode parentModelNode;
if (selectedModelNode.hasParentProperty()) if (selectedModelNode.hasParentProperty())
@@ -983,6 +993,22 @@ void DesignerActionManager::createDefaultDesignerActions()
addDesignerAction(new ChangeStyleAction()); 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) void DesignerActionManager::addDesignerAction(ActionInterface *newAction)
{ {
m_designerActions.append(QSharedPointer<ActionInterface>(newAction)); m_designerActions.append(QSharedPointer<ActionInterface>(newAction));

View File

@@ -42,6 +42,25 @@ namespace QmlDesigner {
class DesignerActionManagerView; class DesignerActionManagerView;
typedef std::function<bool (const QString &filename, const QString &targetDirectory)> 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 class DesignerActionToolBar : public Utils::StyledBar
{ {
public: public:
@@ -64,6 +83,7 @@ public:
QList<ActionInterface* > designerActions() const; QList<ActionInterface* > designerActions() const;
void createDefaultDesignerActions(); void createDefaultDesignerActions();
void createDefaultAddResourceHandler();
DesignerActionManagerView *view(); DesignerActionManagerView *view();
DesignerActionToolBar *createToolBar(QWidget *parent = 0) const; DesignerActionToolBar *createToolBar(QWidget *parent = 0) const;
@@ -76,9 +96,13 @@ public:
DesignerActionManager(const DesignerActionManager&) = delete; DesignerActionManager(const DesignerActionManager&) = delete;
DesignerActionManager & operator=(const DesignerActionManager&) = delete; DesignerActionManager & operator=(const DesignerActionManager&) = delete;
QList<AddResourceHandler> addResourceHandler() const;
void registerAddResourceHandler(const AddResourceHandler &handler);
private: private:
QList<QSharedPointer<ActionInterface> > m_designerActions; QList<QSharedPointer<ActionInterface> > m_designerActions;
DesignerActionManagerView *m_designerActionManagerView; DesignerActionManagerView *m_designerActionManagerView;
QList<AddResourceHandler> m_addResourceHandler;
}; };
} //QmlDesigner } //QmlDesigner

View File

@@ -53,7 +53,7 @@ void DesignerActionManagerView::modelAboutToBeDetached(Model *model)
void DesignerActionManagerView::nodeCreated(const ModelNode &) void DesignerActionManagerView::nodeCreated(const ModelNode &)
{ {
setupContext(); setupContext(SelectionContext::UpdateMode::Fast);
} }
void DesignerActionManagerView::nodeRemoved(const ModelNode &, const NodeAbstractProperty &, AbstractView::PropertyChangeFlags) 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) 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) void DesignerActionManagerView::nodeReparented(const ModelNode &, const NodeAbstractProperty &, const NodeAbstractProperty &, AbstractView::PropertyChangeFlags)
{ {
setupContext(); setupContext(SelectionContext::UpdateMode::Fast);
} }
void DesignerActionManagerView::propertiesRemoved(const QList<AbstractProperty> &) void DesignerActionManagerView::propertiesRemoved(const QList<AbstractProperty> &)
{ {
setupContext(); setupContext(SelectionContext::UpdateMode::Fast);
} }
void DesignerActionManagerView::rootNodeTypeChanged(const QString &, int, int) void DesignerActionManagerView::rootNodeTypeChanged(const QString &, int, int)
@@ -96,7 +96,7 @@ void DesignerActionManagerView::rewriterEndTransaction()
void DesignerActionManagerView::currentStateChanged(const ModelNode &) void DesignerActionManagerView::currentStateChanged(const ModelNode &)
{ {
setupContext(); setupContext(SelectionContext::UpdateMode::Fast);
} }
void DesignerActionManagerView::selectedNodesChanged(const QList<ModelNode> &selectedNodes, const QList<ModelNode> &) void DesignerActionManagerView::selectedNodesChanged(const QList<ModelNode> &selectedNodes, const QList<ModelNode> &)
@@ -112,7 +112,7 @@ void DesignerActionManagerView::selectedNodesChanged(const QList<ModelNode> &sel
void DesignerActionManagerView::nodeOrderChanged(const NodeListProperty &, const ModelNode &, int) void DesignerActionManagerView::nodeOrderChanged(const NodeListProperty &, const ModelNode &, int)
{ {
setupContext(); setupContext(SelectionContext::UpdateMode::Fast);
} }
void DesignerActionManagerView::importsChanged(const QList<Import> &, const QList<Import> &) void DesignerActionManagerView::importsChanged(const QList<Import> &, const QList<Import> &)
@@ -127,21 +127,21 @@ void DesignerActionManagerView::setDesignerActionList(const QList<ActionInterfac
void DesignerActionManagerView::signalHandlerPropertiesChanged(const QVector<SignalHandlerProperty> &, AbstractView::PropertyChangeFlags) void DesignerActionManagerView::signalHandlerPropertiesChanged(const QVector<SignalHandlerProperty> &, AbstractView::PropertyChangeFlags)
{ {
setupContext(); setupContext(SelectionContext::UpdateMode::Fast);
} }
void DesignerActionManagerView::variantPropertiesChanged(const QList<VariantProperty> &, AbstractView::PropertyChangeFlags propertyChangeFlag) void DesignerActionManagerView::variantPropertiesChanged(const QList<VariantProperty> &, AbstractView::PropertyChangeFlags propertyChangeFlag)
{ {
if (propertyChangeFlag == AbstractView::PropertiesAdded) if (propertyChangeFlag == AbstractView::PropertiesAdded)
setupContext(); setupContext(SelectionContext::UpdateMode::Fast);
else if (hasSingleSelectedModelNode()) else if (hasSingleSelectedModelNode())
setupContext(); setupContext(SelectionContext::UpdateMode::Fast);
} }
void DesignerActionManagerView::bindingPropertiesChanged(const QList<BindingProperty> &, AbstractView::PropertyChangeFlags propertyChangeFlag) void DesignerActionManagerView::bindingPropertiesChanged(const QList<BindingProperty> &, AbstractView::PropertyChangeFlags propertyChangeFlag)
{ {
if (propertyChangeFlag == AbstractView::PropertiesAdded) if (propertyChangeFlag == AbstractView::PropertiesAdded)
setupContext(); setupContext(SelectionContext::UpdateMode::Fast);
} }
void DesignerActionManagerView::instancePropertyChanged(const QList<QPair<ModelNode, PropertyName> > &) void DesignerActionManagerView::instancePropertyChanged(const QList<QPair<ModelNode, PropertyName> > &)

View File

@@ -56,6 +56,10 @@
#include <qmljseditor/qmljsfindreferences.h> #include <qmljseditor/qmljsfindreferences.h>
#include <projectexplorer/project.h>
#include <projectexplorer/projectnodes.h>
#include <projectexplorer/projecttree.h>
#include <utils/algorithm.h> #include <utils/algorithm.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
@@ -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 } // namespace Mode
} //QmlDesigner } //QmlDesigner

View File

@@ -72,7 +72,7 @@ void addItemToStackedContainer(const SelectionContext &selectionContext);
void increaseIndexOfStackedContainer(const SelectionContext &selectionContext); void increaseIndexOfStackedContainer(const SelectionContext &selectionContext);
void decreaseIndexOfStackedContainer(const SelectionContext &selectionContext); void decreaseIndexOfStackedContainer(const SelectionContext &selectionContext);
void addTabBarToStackedContainer(const SelectionContext &selectionContext); void addTabBarToStackedContainer(const SelectionContext &selectionContext);
bool addImageToProject(const QString &fileName, const QString &directory);
} // namespace ModelNodeOperationso } // namespace ModelNodeOperationso
} //QmlDesigner } //QmlDesigner

View File

@@ -397,7 +397,7 @@ void FormEditorView::changeToCustomTool()
int handlingRank = 0; int handlingRank = 0;
AbstractCustomTool *selectedCustomTool = 0; AbstractCustomTool *selectedCustomTool = 0;
const ModelNode &selectedModelNode = selectedModelNodes().constFirst(); const ModelNode selectedModelNode = selectedModelNodes().constFirst();
foreach (AbstractCustomTool *customTool, m_customToolList) { foreach (AbstractCustomTool *customTool, m_customToolList) {
if (customTool->wantHandleItem(selectedModelNode) > handlingRank) { if (customTool->wantHandleItem(selectedModelNode) > handlingRank) {

View File

@@ -45,9 +45,11 @@
#include <coreplugin/coreconstants.h> #include <coreplugin/coreconstants.h>
#include <coreplugin/icore.h> #include <coreplugin/icore.h>
#include <coreplugin/messagebox.h>
#include <QApplication> #include <QApplication>
#include <QDrag> #include <QDrag>
#include <QFileDialog>
#include <QFileInfo> #include <QFileInfo>
#include <QFileSystemModel> #include <QFileSystemModel>
#include <QGridLayout> #include <QGridLayout>
@@ -76,6 +78,7 @@ ItemLibraryWidget::ItemLibraryWidget(QWidget *parent) :
m_itemViewQuickWidget(new QQuickWidget), m_itemViewQuickWidget(new QQuickWidget),
m_resourcesView(new ItemLibraryResourceView(this)), m_resourcesView(new ItemLibraryResourceView(this)),
m_importTagsWidget(new QWidget(this)), m_importTagsWidget(new QWidget(this)),
m_addResourcesWidget(new QWidget(this)),
m_filterFlag(QtBasic) m_filterFlag(QtBasic)
{ {
m_compressionTimer.setInterval(200); m_compressionTimer.setInterval(200);
@@ -148,7 +151,8 @@ ItemLibraryWidget::ItemLibraryWidget(QWidget *parent) :
layout->addWidget(spacer, 1, 0); layout->addWidget(spacer, 1, 0);
layout->addWidget(lineEditFrame, 2, 0, 1, 1); layout->addWidget(lineEditFrame, 2, 0, 1, 1);
layout->addWidget(m_importTagsWidget.data(), 3, 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()); setSearchFilter(QString());
@@ -164,6 +168,20 @@ ItemLibraryWidget::ItemLibraryWidget(QWidget *parent) :
auto *flowLayout = new Utils::FlowLayout(m_importTagsWidget.data()); auto *flowLayout = new Utils::FlowLayout(m_importTagsWidget.data());
flowLayout->setMargin(4); 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 // init the first load of the QML UI elements
reloadQmlSource(); reloadQmlSource();
} }
@@ -232,12 +250,15 @@ void ItemLibraryWidget::setCurrentIndexOfStackedWidget(int index)
if (index == 2) { if (index == 2) {
m_filterLineEdit->setVisible(false); m_filterLineEdit->setVisible(false);
m_importTagsWidget->setVisible(true); m_importTagsWidget->setVisible(true);
m_addResourcesWidget->setVisible(false);
} if (index == 1) { } if (index == 1) {
m_filterLineEdit->setVisible(true); m_filterLineEdit->setVisible(true);
m_importTagsWidget->setVisible(false); m_importTagsWidget->setVisible(false);
m_addResourcesWidget->setVisible(true);
} else { } else {
m_filterLineEdit->setVisible(true); m_filterLineEdit->setVisible(true);
m_importTagsWidget->setVisible(true); m_importTagsWidget->setVisible(true);
m_addResourcesWidget->setVisible(false);
} }
m_stackedWidget->setCurrentIndex(index); m_stackedWidget->setCurrentIndex(index);
@@ -279,6 +300,7 @@ void ItemLibraryWidget::setupImportTagWidget()
button->setIcon(Utils::Icons::PLUS.icon()); button->setIcon(Utils::Icons::PLUS.icon());
button->setText(import); button->setText(import);
button->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); button->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
button->setToolTip(tr("Add import %1").arg(import));
connect(button, &QToolButton::clicked, this, [this, import]() { connect(button, &QToolButton::clicked, this, [this, import]() {
addPossibleImport(import); addPossibleImport(import);
}); });
@@ -366,4 +388,47 @@ void ItemLibraryWidget::addPossibleImport(const QString &name)
QmlDesignerPlugin::instance()->currentDesignDocument()->updateSubcomponentManager(); QmlDesignerPlugin::instance()->currentDesignDocument()->updateSubcomponentManager();
} }
void ItemLibraryWidget::addResources()
{
auto document = QmlDesignerPlugin::instance()->currentDesignDocument();
QTC_ASSERT(document, return);
QList<AddResourceHandler> handlers = QmlDesignerPlugin::instance()->viewManager().designerActionManager().addResourceHandler();
QMultiMap<QString, QString> 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));
}
}
}
}
} }

View File

@@ -96,6 +96,7 @@ private:
void removeImport(const QString &name); void removeImport(const QString &name);
void addImport(const QString &name, const QString &version); void addImport(const QString &name, const QString &version);
void addPossibleImport(const QString &name); void addPossibleImport(const QString &name);
void addResources();
QTimer m_compressionTimer; QTimer m_compressionTimer;
QSize m_itemIconSize; QSize m_itemIconSize;
@@ -111,6 +112,7 @@ private:
QScopedPointer<QQuickWidget> m_itemViewQuickWidget; QScopedPointer<QQuickWidget> m_itemViewQuickWidget;
QScopedPointer<ItemLibraryResourceView> m_resourcesView; QScopedPointer<ItemLibraryResourceView> m_resourcesView;
QScopedPointer<QWidget> m_importTagsWidget; QScopedPointer<QWidget> m_importTagsWidget;
QScopedPointer<QWidget> m_addResourcesWidget;
QShortcut *m_qmlSourceUpdateShortcut; QShortcut *m_qmlSourceUpdateShortcut;

View File

@@ -27,6 +27,7 @@
#include "navigatorview.h" #include "navigatorview.h"
#include <bindingproperty.h> #include <bindingproperty.h>
#include <designersettings.h>
#include <nodeabstractproperty.h> #include <nodeabstractproperty.h>
#include <nodehints.h> #include <nodehints.h>
#include <nodelistproperty.h> #include <nodelistproperty.h>
@@ -207,7 +208,8 @@ QVariant NavigatorTreeModel::data(const QModelIndex &index, int role) const
} else if (role == Qt::ToolTipRole) { } else if (role == Qt::ToolTipRole) {
if (currentQmlObjectNode.hasError()) { if (currentQmlObjectNode.hasError()) {
QString errorString = currentQmlObjectNode.error(); 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( 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")))); tr("Use QML emulation layer that is built with the selected Qt"))));

View File

@@ -145,7 +145,7 @@ void PropertyEditorContextObject::toogleExportAlias()
if (rewriterView->selectedModelNodes().isEmpty()) if (rewriterView->selectedModelNodes().isEmpty())
return; return;
const ModelNode &selectedNode = rewriterView->selectedModelNodes().constFirst(); const ModelNode selectedNode = rewriterView->selectedModelNodes().constFirst();
if (QmlObjectNode::isValidQmlObjectNode(selectedNode)) { if (QmlObjectNode::isValidQmlObjectNode(selectedNode)) {
QmlObjectNode objectNode(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 int PropertyEditorContextObject::majorVersion() const
{ {
return m_majorVersion; return m_majorVersion;
@@ -270,6 +289,20 @@ void PropertyEditorContextObject::setMinorVersion(int minorVersion)
emit minorVersionChanged(); 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) void PropertyEditorContextObject::insertInQmlContext(QQmlContext *context)
{ {
m_qmlContext = context; m_qmlContext = context;

View File

@@ -55,6 +55,8 @@ class PropertyEditorContextObject : public QObject
Q_PROPERTY(bool hasAliasExport READ hasAliasExport NOTIFY hasAliasExportChanged) 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(QQmlPropertyMap* backendValues READ backendValues WRITE setBackendValues NOTIFY backendValuesChanged)
Q_PROPERTY(QQmlComponent* specificQmlComponent READ specificQmlComponent NOTIFY specificQmlComponentChanged) Q_PROPERTY(QQmlComponent* specificQmlComponent READ specificQmlComponent NOTIFY specificQmlComponentChanged)
@@ -81,6 +83,7 @@ public:
Q_INVOKABLE void toogleExportAlias(); Q_INVOKABLE void toogleExportAlias();
Q_INVOKABLE void changeTypeName(const QString &typeName); Q_INVOKABLE void changeTypeName(const QString &typeName);
Q_INVOKABLE void insertKeyframe(const QString &propertyName);
int majorVersion() const; int majorVersion() const;
int majorQtQuickVersion() const; int majorQtQuickVersion() const;
@@ -91,6 +94,9 @@ public:
int minorVersion() const; int minorVersion() const;
void setMinorVersion(int minorVersion); void setMinorVersion(int minorVersion);
bool hasActiveTimeline() const;
void setHasActiveTimeline(bool b);
void insertInQmlContext(QQmlContext *context); void insertInQmlContext(QQmlContext *context);
QQmlComponent *specificQmlComponent(); QQmlComponent *specificQmlComponent();
@@ -110,6 +116,7 @@ signals:
void minorQtQuickVersionChanged(); void minorQtQuickVersionChanged();
void specificQmlComponentChanged(); void specificQmlComponentChanged();
void hasAliasExportChanged(); void hasAliasExportChanged();
void hasActiveTimelineChanged();
public slots: public slots:
void setGlobalBaseUrl(const QUrl &newBaseUrl); void setGlobalBaseUrl(const QUrl &newBaseUrl);
@@ -153,6 +160,8 @@ private:
Model *m_model = nullptr; Model *m_model = nullptr;
bool m_aliasExport = false; bool m_aliasExport = false;
bool m_setHasActiveTimeline = false;
}; };
} //QmlDesigner { } //QmlDesigner {

View File

@@ -29,6 +29,7 @@
#include "propertyeditortransaction.h" #include "propertyeditortransaction.h"
#include <qmldesignerconstants.h> #include <qmldesignerconstants.h>
#include <qmldesignerplugin.h> #include <qmldesignerplugin.h>
#include <qmltimelinemutator.h>
#include <qmlobjectnode.h> #include <qmlobjectnode.h>
#include <nodemetainfo.h> #include <nodemetainfo.h>
@@ -328,6 +329,9 @@ void PropertyEditorQmlBackend::setup(const QmlObjectNode &qmlObjectNode, const Q
contextObject()->setIsBaseState(qmlObjectNode.isInBaseState()); contextObject()->setIsBaseState(qmlObjectNode.isInBaseState());
contextObject()->setHasAliasExport(qmlObjectNode.isAliasExported()); contextObject()->setHasAliasExport(qmlObjectNode.isAliasExported());
contextObject()->setHasActiveTimeline(QmlTimelineMutator::hasActiveTimeline(qmlObjectNode.view()));
contextObject()->setSelectionChanged(false); contextObject()->setSelectionChanged(false);
contextObject()->setSelectionChanged(false); contextObject()->setSelectionChanged(false);

Some files were not shown because too many files have changed in this diff Show More