Merge remote-tracking branch 'origin/4.6'
Conflicts: share/qtcreator/qml-type-descriptions/qmlproject.qmltypes src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp Change-Id: I35fb652f29a98a798be7c8b4b4c2e581eb175fb6
23
README.md
@@ -277,6 +277,29 @@ http://llvm.org/docs/GettingStarted.html#git-mirror:
|
||||
Qt Creator includes the following third-party components,
|
||||
we thank the authors who made this possible:
|
||||
|
||||
### Clazy
|
||||
|
||||
https://github.com/KDE/clazy
|
||||
|
||||
Copyright (C) 2015-2018 Clazy Team
|
||||
|
||||
Distributed under GNU LIBRARY GENERAL PUBLIC LICENSE Version 2 (LGPL2).
|
||||
|
||||
Integrated with patches from QtCreator/dist/clang/patches, see README.md there.
|
||||
|
||||
### LLVM/Clang
|
||||
|
||||
http://llvm.org/svn/llvm-project/llvm
|
||||
http://llvm.org/svn/llvm-project/cfe/trunk
|
||||
http://llvm.org/svn/llvm-project/clang-tools-extra/trunk
|
||||
|
||||
Copyright (C) 2003-2018 LLVM Team
|
||||
|
||||
Distributed under the University of Illinois/NCSA Open Source License (NCSA),
|
||||
see https://github.com/llvm-mirror/llvm/blob/master/LICENSE.TXT
|
||||
|
||||
With additional patches from QtCreator/dist/clang/patches, see README.md there.
|
||||
|
||||
### Reference implementation for std::experimental::optional
|
||||
|
||||
https://github.com/akrzemi1/Optional
|
||||
|
||||
147
dist/changes-4.6.0.md
vendored
Normal 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
|
||||
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 58 KiB After Width: | Height: | Size: 70 KiB |
|
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 47 KiB |
|
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 22 KiB |
@@ -75,8 +75,8 @@
|
||||
useful if the code contains typos, for example.
|
||||
|
||||
Clang keeps up with the development of the C++ language. At the time of this
|
||||
writing, it supports C++98/03, C++11, C++14, C89, C99, Objective-C, and
|
||||
Objective-C++.
|
||||
writing, it supports C++98/03, C++11, C++14, C++17, C89, C99, Objective-C,
|
||||
and Objective-C++.
|
||||
|
||||
On the downside, for large projects using Clang as code model is slower than
|
||||
using the built-in code model. Clang does not need to generate object files,
|
||||
@@ -94,11 +94,27 @@
|
||||
\li Syntactic and semantic highlighting
|
||||
\li Diagnostics
|
||||
\li Tooltips
|
||||
\li Clang-Tidy and Clazy checks
|
||||
\li Renaming of local symbols
|
||||
|
||||
\endlist
|
||||
|
||||
To use the plugin, you must activate it and configure it in \QC.
|
||||
|
||||
\section1 Using Clang-Tidy and Clazy
|
||||
|
||||
\l{https://clang.llvm.org/extra/clang-tidy/}{Clang-Tidy} and
|
||||
\l{https://github.com/KDE/clazy/blob/master/README.md}{Clazy} are delivered
|
||||
as parts of the Clang library delivered with \QC.
|
||||
|
||||
Clang-Tidy provides an extensible framework for diagnosing and fixing
|
||||
typical programming errors, such as style violations, interface misuse, or
|
||||
issues that can be found via static analysis.
|
||||
|
||||
Clazy helps Clang understand Qt semantics. It prints out Qt related compiler
|
||||
warnings, ranging from unnecessary memory allocation to misuse of API and
|
||||
provides refactoring actions for fixing some of the issues.
|
||||
|
||||
\section1 Activating Clang Code Model
|
||||
|
||||
If you build \QC yourself, ensure that the plugin is also built, as
|
||||
@@ -176,6 +192,9 @@
|
||||
{Options to Request or Suppress Warnings} or the GCC or Clang
|
||||
manual pages.
|
||||
|
||||
\li In the \uicontrol {Clang Plugins} field, select the Clang-Tidy and
|
||||
Clazy checks to perform.
|
||||
|
||||
\endlist
|
||||
|
||||
You can specify Clang settings at project level in the build settings of
|
||||
|
||||
@@ -2851,6 +2851,9 @@
|
||||
\li Locating files belonging to your project (\c {p}), such as source,
|
||||
header resource, and \c {.ui} files, or to any project (\c {a})
|
||||
|
||||
\li Locating bookmarks (\c {b}).
|
||||
For more information, see \l{Using Bookmarks}.
|
||||
|
||||
\li Locating class (\c {c}), enum, and function (m) definitions in your
|
||||
project or anywhere referenced from your project (\c {:})
|
||||
|
||||
@@ -2874,6 +2877,8 @@
|
||||
\li Executing version control system commands (\c {git}). For more
|
||||
information, see \l{Using Version Control Systems}
|
||||
|
||||
\li Triggering menu items from the main menu (\c {t})
|
||||
|
||||
\li Running external tools (\c x)
|
||||
|
||||
\endlist
|
||||
@@ -2914,6 +2919,10 @@
|
||||
followed by \key Space, followed by path and file name, and then press
|
||||
\key Enter.
|
||||
|
||||
You can use the filter that triggers menu commands to open sessions. Enter
|
||||
\c {t yoursess} or \c {t sess yoursess} to trigger \uicontrol File >
|
||||
\uicontrol Sessions > \e yoursessionname.
|
||||
|
||||
By default, the following filters are enabled and you do not need to use
|
||||
their prefixes explicitly:
|
||||
|
||||
|
||||
@@ -98,6 +98,9 @@
|
||||
|
||||
\image qtcreator-welcome-session.png
|
||||
|
||||
You can also use the \c t locator filter to open a session. For more
|
||||
information, see \l{Searching with the Locator}.
|
||||
|
||||
To view more information about a session, select the down arrow icon that
|
||||
appears when you move the mouse cursor over the session name. Select actions
|
||||
to clone, rename, and delete sessions.
|
||||
|
||||
@@ -261,7 +261,11 @@
|
||||
\image qtcreator-filesystem-view.png
|
||||
|
||||
By default, the contents of the directory that contains the file currently
|
||||
active in the editor are displayed. To move to the root directory of the
|
||||
active in the editor are displayed. The path to the active file is displayed
|
||||
as bread crumbs. You can move to any directory along the path by clicking
|
||||
it.
|
||||
|
||||
To move to the root directory of the
|
||||
file system, select \uicontrol Computer in the menu (1). Select
|
||||
\uicontrol Home to move to the user's home directory. Further, you can
|
||||
select a project to move to an open project or \uicontrol Projects to open
|
||||
@@ -288,6 +292,14 @@
|
||||
|
||||
\li Search from the selected directory.
|
||||
|
||||
\li Create new files. For more information, see
|
||||
\l{Adding Files to Projects}.
|
||||
|
||||
\li Rename or remove existing files.
|
||||
|
||||
\li Compare the selected file with the currently open file in the diff
|
||||
editor. For more information, see \l{Comparing Files}.
|
||||
|
||||
\li Display the contents of a particular directory in the view.
|
||||
|
||||
\endlist
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Copyright (C) 2018 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the Qt Creator documentation.
|
||||
@@ -124,6 +124,9 @@
|
||||
\uicontrol {Fixup Previous Commit}. This operation is done using interactive
|
||||
rebase. In case of conflicts, a merge tool is suggested.
|
||||
|
||||
To recover removed files, select \uicontrol Tools > \uicontrol Git >
|
||||
\uicontrol {Recover Deleted Files}.
|
||||
|
||||
To change a series of commits in the local repository, select
|
||||
\uicontrol Tools > \uicontrol Git > \uicontrol {Local Repository} >
|
||||
\uicontrol {Interactive Rebase}. You can reorder or discard commits, squash
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Copyright (C) 2018 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the Qt Creator documentation.
|
||||
@@ -234,6 +234,9 @@
|
||||
show annotation views of previous versions (see \l{Annotating Files}).
|
||||
With Git you can also choose to cherry-pick or revert a change.
|
||||
|
||||
With Git, you can click \inlineimage reload_gray.png
|
||||
(\uicontrol Reload) to rescan the files.
|
||||
|
||||
\section2 Annotating Files
|
||||
|
||||
Annotation views are obtained by selecting \uicontrol{Annotate} or \uicontrol{Blame}.
|
||||
@@ -250,6 +253,9 @@
|
||||
The same context menu is available when right-clicking on a version
|
||||
identifier in the file log view of a single file.
|
||||
|
||||
With Git, you can click \inlineimage reload_gray.png
|
||||
(\uicontrol Reload) to rescan the files.
|
||||
|
||||
\section2 Committing Changes
|
||||
|
||||
Once you have finished making changes, submit them to the version control
|
||||
|
||||
@@ -16,7 +16,10 @@ function readOutput(executable, args)
|
||||
|
||||
function readListOutput(executable, args)
|
||||
{
|
||||
return readOutput(executable, args).split(/\s+/);
|
||||
var list = readOutput(executable, args).split(/\s+/);
|
||||
if (!list[list.length - 1])
|
||||
list.pop();
|
||||
return list;
|
||||
}
|
||||
|
||||
function isSuitableLLVMConfig(llvmConfigCandidate, qtcFunctions)
|
||||
|
||||
@@ -9,6 +9,7 @@ Module {
|
||||
property bool enableUnitTests: false
|
||||
property bool enableProjectFileUpdates: true
|
||||
property bool installApiHeaders: false
|
||||
property bool enableBundledQt: false
|
||||
property string libInstallDir: qtc.ide_library_path
|
||||
property stringList libRPaths: qbs.targetOS.contains("macos")
|
||||
? ["@loader_path/" + FileInfo.relativePath('/' + appInstallDir, '/' + libInstallDir)]
|
||||
|
||||
@@ -118,7 +118,7 @@ macx {
|
||||
} else {
|
||||
BINDIST_SOURCE = "$(INSTALL_ROOT)$$QTC_PREFIX"
|
||||
BINDIST_EXCLUDE_ARG = "--exclude-toplevel"
|
||||
deployqt.commands = python -u $$PWD/scripts/deployqt.py -i \"$(INSTALL_ROOT)$$QTC_PREFIX\" \"$(QMAKE)\"
|
||||
deployqt.commands = python -u $$PWD/scripts/deployqt.py -i \"$(INSTALL_ROOT)$$QTC_PREFIX/bin/$${IDE_APP_TARGET}\" \"$(QMAKE)\"
|
||||
deployqt.depends = install
|
||||
win32 {
|
||||
deployartifacts.depends = install
|
||||
|
||||
@@ -43,7 +43,7 @@ debug_build = False
|
||||
encoding = locale.getdefaultlocale()[1]
|
||||
|
||||
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 is_exe(fpath):
|
||||
@@ -77,9 +77,6 @@ def is_debug(fpath):
|
||||
output = subprocess.check_output(['dumpbin', '/imports', fpath])
|
||||
return coredebug.search(output.decode(encoding)) != None
|
||||
|
||||
def is_debug_build(install_dir):
|
||||
return is_debug(os.path.join(install_dir, 'bin', 'qtcreator.exe'))
|
||||
|
||||
def op_failed(details = None):
|
||||
if details != None:
|
||||
print(details)
|
||||
@@ -274,11 +271,16 @@ def main():
|
||||
ignoreErrors = True
|
||||
print("Note: Ignoring all errors")
|
||||
|
||||
if len(args) < 1:
|
||||
qtcreator_binary = os.path.abspath(args[0])
|
||||
if common.is_windows_platform() and not qtcreator_binary.lower().endswith(".exe"):
|
||||
qtcreator_binary = qtcreator_binary + ".exe"
|
||||
|
||||
if len(args) < 1 or not os.path.isfile(qtcreator_binary):
|
||||
usage()
|
||||
sys.exit(2)
|
||||
|
||||
install_dir = args[0]
|
||||
qtcreator_binary_path = os.path.dirname(qtcreator_binary)
|
||||
install_dir = os.path.abspath(os.path.join(qtcreator_binary_path, '..'))
|
||||
if common.is_linux_platform():
|
||||
qt_deploy_prefix = os.path.join(install_dir, 'lib', 'Qt')
|
||||
else:
|
||||
@@ -307,12 +309,14 @@ def main():
|
||||
QT_INSTALL_QML = qt_install_info['QT_INSTALL_QML']
|
||||
QT_INSTALL_TRANSLATIONS = qt_install_info['QT_INSTALL_TRANSLATIONS']
|
||||
|
||||
plugins = ['accessible', 'codecs', 'designer', 'iconengines', 'imageformats', 'platformthemes', 'platforminputcontexts', 'platforms', 'printsupport', 'sqldrivers', 'styles', 'xcbglintegrations']
|
||||
plugins = ['accessible', 'codecs', 'designer', 'iconengines', 'imageformats', 'platformthemes',
|
||||
'platforminputcontexts', 'platforms', 'printsupport', 'sqldrivers', 'styles',
|
||||
'xcbglintegrations', 'qmltooling']
|
||||
imports = ['Qt', 'QtWebKit']
|
||||
|
||||
if common.is_windows_platform():
|
||||
global debug_build
|
||||
debug_build = is_debug_build(install_dir)
|
||||
debug_build = is_debug(qtcreator_binary)
|
||||
|
||||
if common.is_windows_platform():
|
||||
copy_qt_libs(qt_deploy_prefix, QT_INSTALL_BINS, QT_INSTALL_BINS, QT_INSTALL_PLUGINS, QT_INSTALL_IMPORTS, QT_INSTALL_QML, plugins, imports)
|
||||
|
||||
@@ -41,8 +41,9 @@ use warnings;
|
||||
while (my $line = <STDIN>) {
|
||||
chomp($line);
|
||||
# --- extract file name based matching:
|
||||
# D:/.../qaxbase.cpp:3231: warning: Cannot tie this documentation to anything
|
||||
if ($line =~ /^(..[^:]*):(\d+): warning: (.*)$/) {
|
||||
# Qt 5.10: D:/.../qaxbase.cpp:3231: warning: Cannot tie this documentation to anything
|
||||
# Qt 5.11: D:/.../qaxbase.cpp:3231: (qdoc) warning: Cannot tie this documentation to anything
|
||||
if ($line =~ /^(..[^:]*):(\d+): (?:\(qdoc\) )?warning: (.*)$/) {
|
||||
my $fileName = $1;
|
||||
my $lineNumber = $2;
|
||||
my $text = $3;
|
||||
|
||||
@@ -11,7 +11,7 @@ Module {
|
||||
"QmlProject/Project 1.1"
|
||||
]
|
||||
Property { name: "sourceDirectory"; type: "string" }
|
||||
Property { name: "targetDirectory": type: "string" }
|
||||
Property { name: "targetDirectory"; type: "string" }
|
||||
Property { name: "mainFile"; type: "string" }
|
||||
Property { name: "importPaths"; type: "string"; isList: true }
|
||||
Property { name: "content"; type: "QmlProjectItem"; isList: true }
|
||||
|
||||
@@ -155,6 +155,12 @@ Item {
|
||||
}
|
||||
checkable: true
|
||||
}
|
||||
|
||||
Controls.MenuItem {
|
||||
text: qsTr("Insert keyframe")
|
||||
visible: hasActiveTimeline
|
||||
onTriggered: insertKeyframe(backendValue.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
"trDescription": "Creates a scratch model using a temporary file.",
|
||||
"trDisplayName": "Scratch Model",
|
||||
"trDisplayCategory": "Modeling",
|
||||
"iconText": "qmodel",
|
||||
"platformIndependent": true,
|
||||
"enabled": "%{JS: [ %{Plugins} ].indexOf('ModelEditor') >= 0}",
|
||||
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
cmake_minimum_required(VERSION 2.8.12)
|
||||
cmake_minimum_required(VERSION 3.1)
|
||||
|
||||
project(%{ProjectName} LANGUAGES CXX)
|
||||
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTORCC ON)
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
find_package(Qt5 COMPONENTS Core Quick REQUIRED)
|
||||
|
||||
|
||||
@@ -57589,7 +57589,7 @@ Má se to zkusit ještě jednou?</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>QmlProfiler::Internal::QmlProfilerEventsMainView</name>
|
||||
<name>QmlProfiler::Internal::QmlProfilerStatisticsMainView</name>
|
||||
<message>
|
||||
<source>Location</source>
|
||||
<translation>Umístění</translation>
|
||||
|
||||
@@ -58942,7 +58942,7 @@ Voulez-vous la tuer ?</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>QmlProfiler::Internal::QmlProfilerEventsMainView</name>
|
||||
<name>QmlProfiler::Internal::QmlProfilerStatisticsMainView</name>
|
||||
<message>
|
||||
<source>Location</source>
|
||||
<translation>Emplacement</translation>
|
||||
|
||||
@@ -30492,7 +30492,7 @@ Do you want to kill it?</source>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>QmlProfiler::Internal::QmlProfilerEventsMainView</name>
|
||||
<name>QmlProfiler::Internal::QmlProfilerStatisticsMainView</name>
|
||||
<message>
|
||||
<source>Location</source>
|
||||
<translation type="vanished">Розташування</translation>
|
||||
|
||||
@@ -55655,7 +55655,7 @@ Do you want to retry?</source>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>QmlProfiler::Internal::QmlProfilerEventsMainView</name>
|
||||
<name>QmlProfiler::Internal::QmlProfilerStatisticsMainView</name>
|
||||
<message>
|
||||
<source>Location</source>
|
||||
<translation>路径</translation>
|
||||
|
||||
@@ -32076,7 +32076,7 @@ Do you want to kill it?</source>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>QmlProfiler::Internal::QmlProfilerEventsMainView</name>
|
||||
<name>QmlProfiler::Internal::QmlProfilerStatisticsMainView</name>
|
||||
<message>
|
||||
<source>Location</source>
|
||||
<translation>位置</translation>
|
||||
|
||||
@@ -153,9 +153,10 @@ Item {
|
||||
spacing: innerMargin
|
||||
columns: 2
|
||||
property int minimumWidth: {
|
||||
// max(width of longest label * 2, minimumInnerWidth)
|
||||
var result = minimumInnerWidth;
|
||||
for (var i = 0; i < children.length; ++i)
|
||||
result = Math.max(children[i].x, result);
|
||||
for (var i = 0; i < children.length; i += 2)
|
||||
result = Math.max(children[i].implicitWidth * 2 + innerMargin, result);
|
||||
return result + 2 * outerMargin;
|
||||
}
|
||||
|
||||
@@ -170,8 +171,8 @@ Item {
|
||||
property bool isLabel: index % 2 === 0
|
||||
font.bold: isLabel
|
||||
elide: Text.ElideRight
|
||||
width: text === "" ? 0 : (isLabel ? implicitWidth :
|
||||
(dragHandle.x - x - innerMargin))
|
||||
width: (text === "" || isLabel)
|
||||
? implicitWidth : (dragHandle.x - col.minimumWidth / 2 - innerMargin)
|
||||
text: isLabel ? (modelData + ":") : modelData
|
||||
color: contentTextColor
|
||||
}
|
||||
|
||||
@@ -176,9 +176,10 @@ Item {
|
||||
spacing: 5
|
||||
columns: 2
|
||||
property int minimumWidth: {
|
||||
// max(width of longest label * 2, 150)
|
||||
var result = 150;
|
||||
for (var i = 0; i < children.length; ++i)
|
||||
result = Math.max(children[i].x, result);
|
||||
for (var i = 0; i < children.length; i += 2)
|
||||
result = Math.max(children[i].implicitWidth * 2 + spacing, result);
|
||||
return result + 20;
|
||||
}
|
||||
|
||||
@@ -190,7 +191,7 @@ Item {
|
||||
Repeater {
|
||||
model: eventInfo
|
||||
Detail {
|
||||
valueWidth: dragHandle.x - x - 15
|
||||
valueWidth: (dragHandle.x - col.minimumWidth / 2 - col.spacing)
|
||||
isLabel: index % 2 === 0
|
||||
text: (content === undefined) ? "" : (isLabel ? (content + ":") : content)
|
||||
}
|
||||
|
||||
@@ -500,7 +500,7 @@ Environment::const_iterator Environment::constEnd() const
|
||||
|
||||
Environment::const_iterator Environment::constFind(const QString &name) const
|
||||
{
|
||||
return m_values.constFind(name);
|
||||
return findKey(m_values, m_osType, name);
|
||||
}
|
||||
|
||||
int Environment::size() const
|
||||
@@ -567,6 +567,11 @@ bool Environment::hasKey(const QString &key) const
|
||||
return m_values.contains(key);
|
||||
}
|
||||
|
||||
OsType Environment::osType() const
|
||||
{
|
||||
return m_osType;
|
||||
}
|
||||
|
||||
QString Environment::userName() const
|
||||
{
|
||||
return value(QString::fromLatin1(m_osType == OsTypeWindows ? "USERNAME" : "USER"));
|
||||
|
||||
@@ -91,6 +91,7 @@ public:
|
||||
/// Return the Environment changes necessary to modify this into the other environment.
|
||||
QList<EnvironmentItem> diff(const Environment &other, bool checkAppendPrepend = false) const;
|
||||
bool hasKey(const QString &key) const;
|
||||
OsType osType() const;
|
||||
|
||||
QString userName() const;
|
||||
|
||||
|
||||
@@ -364,6 +364,13 @@ void EnvironmentModel::setUserChanges(QList<EnvironmentItem> list)
|
||||
name = name.trimmed();
|
||||
if (name.startsWith(QLatin1String("export ")))
|
||||
name = name.mid(7).trimmed();
|
||||
if (d->m_baseEnvironment.osType() == OsTypeWindows) {
|
||||
// Environment variable names are case-insensitive under windows, but we still
|
||||
// want to preserve the case of pre-existing variables.
|
||||
auto it = d->m_baseEnvironment.constFind(name);
|
||||
if (it != d->m_baseEnvironment.constEnd())
|
||||
name = d->m_baseEnvironment.key(it);
|
||||
}
|
||||
}
|
||||
|
||||
d->updateResultEnvironment();
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include <cpptools/cppmodelmanager.h>
|
||||
#include <projectexplorer/session.h>
|
||||
#include <utils/algorithm.h>
|
||||
#include <utils/asconst.h>
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
namespace Autotest {
|
||||
@@ -122,100 +123,67 @@ TestConfiguration *GTestTreeItem::debugConfiguration() const
|
||||
return config;
|
||||
}
|
||||
|
||||
QList<TestConfiguration *> GTestTreeItem::getAllTestConfigurations() const
|
||||
{
|
||||
QList<TestConfiguration *> result;
|
||||
|
||||
ProjectExplorer::Project *project = ProjectExplorer::SessionManager::startupProject();
|
||||
if (!project || type() != Root)
|
||||
return result;
|
||||
|
||||
QHash<QString, int> proFilesWithTestSets;
|
||||
QHash<QString, QSet<QString> > proFilesWithInternalTargets;
|
||||
for (int row = 0, count = childCount(); row < count; ++row) {
|
||||
const GTestTreeItem *child = static_cast<const GTestTreeItem *>(childItem(row));
|
||||
|
||||
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();
|
||||
QHash<QString, int>::ConstIterator end = proFilesWithTestSets.end();
|
||||
for ( ; it != end; ++it) {
|
||||
const QSet<QString> &internalTargets = proFilesWithInternalTargets[it.key()];
|
||||
for (const QString &target : internalTargets) {
|
||||
GTestConfiguration *tc = new GTestConfiguration;
|
||||
tc->setTestCaseCount(it.value());
|
||||
tc->setProjectFile(it.key());
|
||||
tc->setProject(project);
|
||||
tc->setInternalTarget(target);
|
||||
result << tc;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
struct TestCases
|
||||
{
|
||||
QStringList filters;
|
||||
int additionalTestCaseCount = 0;
|
||||
int testSetCount = 0;
|
||||
QSet<QString> internalTargets;
|
||||
};
|
||||
|
||||
QList<TestConfiguration *> GTestTreeItem::getSelectedTestConfigurations() const
|
||||
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;
|
||||
ProjectExplorer::Project *project = ProjectExplorer::SessionManager::startupProject();
|
||||
if (!project || type() != Root)
|
||||
return result;
|
||||
|
||||
QHash<QString, TestCases> proFilesWithCheckedTestSets;
|
||||
QHash<QString, QSet<QString> > proFilesWithInternalTargets;
|
||||
QHash<QString, TestCases> testCasesForProFile;
|
||||
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;
|
||||
}
|
||||
}
|
||||
auto child = static_cast<const GTestTreeItem *>(childItem(row));
|
||||
collectTestInfo(child, testCasesForProFile, ignoreCheckState);
|
||||
}
|
||||
|
||||
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) {
|
||||
for (auto it = testCasesForProFile.begin(), end = testCasesForProFile.end(); it != end; ++it) {
|
||||
for (const QString &target : Utils::asConst(it.value().internalTargets)) {
|
||||
GTestConfiguration *tc = new GTestConfiguration;
|
||||
if (!ignoreCheckState)
|
||||
tc->setTestCases(it.value().filters);
|
||||
tc->setTestCaseCount(tc->testCaseCount() + it.value().additionalTestCaseCount);
|
||||
tc->setTestCaseCount(tc->testCaseCount() + it.value().testSetCount);
|
||||
tc->setProjectFile(it.key());
|
||||
tc->setProject(project);
|
||||
tc->setInternalTarget(target);
|
||||
@@ -226,6 +194,16 @@ QList<TestConfiguration *> GTestTreeItem::getSelectedTestConfigurations() const
|
||||
return result;
|
||||
}
|
||||
|
||||
QList<TestConfiguration *> GTestTreeItem::getAllTestConfigurations() const
|
||||
{
|
||||
return getTestConfigurations(true);
|
||||
}
|
||||
|
||||
QList<TestConfiguration *> GTestTreeItem::getSelectedTestConfigurations() const
|
||||
{
|
||||
return getTestConfigurations(false);
|
||||
}
|
||||
|
||||
TestTreeItem *GTestTreeItem::find(const TestParseResult *result)
|
||||
{
|
||||
QTC_ASSERT(result, return nullptr);
|
||||
|
||||
@@ -71,6 +71,7 @@ public:
|
||||
|
||||
private:
|
||||
bool modifyTestSetContent(const GTestParseResult *result);
|
||||
QList<TestConfiguration *> getTestConfigurations(bool ignoreCheckState) const;
|
||||
GTestTreeItem::TestStates m_state;
|
||||
};
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ QtTestTreeItem::QtTestTreeItem(const QString &name, const QString &filePath, Tes
|
||||
: TestTreeItem(name, filePath, type)
|
||||
{
|
||||
if (type == TestDataTag)
|
||||
setChecked(Qt::Checked);
|
||||
setData(0, Qt::Checked, Qt::CheckStateRole);
|
||||
}
|
||||
|
||||
QVariant QtTestTreeItem::data(int column, int role) const
|
||||
@@ -139,6 +139,53 @@ TestConfiguration *QtTestTreeItem::testConfiguration() const
|
||||
return config;
|
||||
}
|
||||
|
||||
static void fillTestConfigurationsFromCheckState(const TestTreeItem *item,
|
||||
QList<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
|
||||
{
|
||||
QtTestConfiguration *config = static_cast<QtTestConfiguration *>(testConfiguration());
|
||||
@@ -157,13 +204,19 @@ QList<TestConfiguration *> QtTestTreeItem::getAllTestConfigurations() const
|
||||
|
||||
for (int row = 0, count = childCount(); row < count; ++row) {
|
||||
const TestTreeItem *child = childItem(row);
|
||||
|
||||
TestConfiguration *tc = new QtTestConfiguration();
|
||||
tc->setTestCaseCount(child->childCount());
|
||||
tc->setProjectFile(child->proFile());
|
||||
tc->setProject(project);
|
||||
tc->setInternalTargets(child->internalTargets());
|
||||
TestConfiguration *tc = nullptr;
|
||||
if (child->type() == TestCase) {
|
||||
tc = child->testConfiguration();
|
||||
QTC_ASSERT(tc, continue);
|
||||
result << tc;
|
||||
} else if (child->type() == GroupNode) {
|
||||
const int groupChildCount = child->childCount();
|
||||
for (int groupChildRow = 0; groupChildRow < groupChildCount; ++groupChildRow) {
|
||||
tc = child->childItem(groupChildRow)->testConfiguration();
|
||||
QTC_ASSERT(tc, continue);
|
||||
result << tc;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -175,49 +228,8 @@ QList<TestConfiguration *> QtTestTreeItem::getSelectedTestConfigurations() const
|
||||
if (!project || type() != Root)
|
||||
return result;
|
||||
|
||||
QtTestConfiguration *testConfiguration = nullptr;
|
||||
|
||||
for (int row = 0, count = childCount(); row < count; ++row) {
|
||||
const TestTreeItem *child = childItem(row);
|
||||
|
||||
switch (child->checked()) {
|
||||
case Qt::Unchecked:
|
||||
continue;
|
||||
case Qt::Checked:
|
||||
testConfiguration = new QtTestConfiguration();
|
||||
testConfiguration->setTestCaseCount(child->childCount());
|
||||
testConfiguration->setProjectFile(child->proFile());
|
||||
testConfiguration->setProject(project);
|
||||
testConfiguration->setInternalTargets(child->internalTargets());
|
||||
result << testConfiguration;
|
||||
continue;
|
||||
case Qt::PartiallyChecked:
|
||||
default:
|
||||
int grandChildCount = child->childCount();
|
||||
QStringList testCases;
|
||||
for (int grandChildRow = 0; grandChildRow < grandChildCount; ++grandChildRow) {
|
||||
const TestTreeItem *grandChild = child->childItem(grandChildRow);
|
||||
if (grandChild->checked() == Qt::Checked) {
|
||||
testCases << grandChild->name();
|
||||
} else if (grandChild->checked() == Qt::PartiallyChecked) {
|
||||
const int dtCount = grandChild->childCount();
|
||||
const QString funcName = grandChild->name();
|
||||
for (int dtRow = 0; dtRow < dtCount; ++dtRow) {
|
||||
const TestTreeItem *dataTag = grandChild->childItem(dtRow);
|
||||
if (dataTag->checked() == Qt::Checked)
|
||||
testCases << funcName + ':' + dataTag->name();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
testConfiguration = new QtTestConfiguration();
|
||||
testConfiguration->setTestCases(testCases);
|
||||
testConfiguration->setProjectFile(child->proFile());
|
||||
testConfiguration->setProject(project);
|
||||
testConfiguration->setInternalTargets(child->internalTargets());
|
||||
result << testConfiguration;
|
||||
}
|
||||
}
|
||||
for (int row = 0, count = childCount(); row < count; ++row)
|
||||
fillTestConfigurationsFromCheckState(childItem(row), result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -153,6 +153,43 @@ TestConfiguration *QuickTestTreeItem::testConfiguration() const
|
||||
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
|
||||
{
|
||||
QuickTestConfiguration *config = static_cast<QuickTestConfiguration *>(testConfiguration());
|
||||
@@ -161,6 +198,17 @@ TestConfiguration *QuickTestTreeItem::debugConfiguration() const
|
||||
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 *> result;
|
||||
@@ -169,8 +217,7 @@ QList<TestConfiguration *> QuickTestTreeItem::getAllTestConfigurations() const
|
||||
if (!project || type() != Root)
|
||||
return result;
|
||||
|
||||
QHash<QString, int> foundProFiles;
|
||||
QHash<QString, QSet<QString> > proFilesWithTargets;
|
||||
QHash<QString, Tests> testsForProfile;
|
||||
for (int row = 0, count = childCount(); row < count; ++row) {
|
||||
const TestTreeItem *child = childItem(row);
|
||||
// unnamed Quick Tests must be handled separately
|
||||
@@ -178,25 +225,29 @@ QList<TestConfiguration *> QuickTestTreeItem::getAllTestConfigurations() const
|
||||
for (int childRow = 0, ccount = child->childCount(); childRow < ccount; ++ childRow) {
|
||||
const TestTreeItem *grandChild = child->childItem(childRow);
|
||||
const QString &proFile = grandChild->proFile();
|
||||
foundProFiles.insert(proFile, foundProFiles[proFile] + 1);
|
||||
proFilesWithTargets.insert(proFile, grandChild->internalTargets());
|
||||
++(testsForProfile[proFile].testCount);
|
||||
testsForProfile[proFile].internalTargets = grandChild->internalTargets();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
// named Quick Test
|
||||
const QString &proFile = child->proFile();
|
||||
foundProFiles.insert(proFile, foundProFiles[proFile] + child->childCount());
|
||||
proFilesWithTargets.insert(proFile, child->internalTargets());
|
||||
if (child->type() == TestCase) {
|
||||
addTestsForItem(testsForProfile[child->proFile()], child);
|
||||
} else if (child->type() == GroupNode) {
|
||||
const int groupCount = child->childCount();
|
||||
for (int groupRow = 0; groupRow < groupCount; ++groupRow) {
|
||||
const TestTreeItem *grandChild = child->childItem(groupRow);
|
||||
addTestsForItem(testsForProfile[grandChild->proFile()], grandChild);
|
||||
}
|
||||
}
|
||||
}
|
||||
// create TestConfiguration for each project file
|
||||
QHash<QString, int>::ConstIterator it = foundProFiles.begin();
|
||||
QHash<QString, int>::ConstIterator end = foundProFiles.end();
|
||||
for ( ; it != end; ++it) {
|
||||
for (auto it = testsForProfile.begin(), end = testsForProfile.end(); it != end; ++it) {
|
||||
QuickTestConfiguration *tc = new QuickTestConfiguration;
|
||||
tc->setTestCaseCount(it.value());
|
||||
tc->setTestCaseCount(it.value().testCount);
|
||||
tc->setProjectFile(it.key());
|
||||
tc->setProject(project);
|
||||
tc->setInternalTargets(proFilesWithTargets[it.key()]);
|
||||
tc->setInternalTargets(it.value().internalTargets);
|
||||
result << tc;
|
||||
}
|
||||
return result;
|
||||
@@ -209,7 +260,6 @@ QList<TestConfiguration *> QuickTestTreeItem::getSelectedTestConfigurations() co
|
||||
if (!project || type() != Root)
|
||||
return result;
|
||||
|
||||
QuickTestConfiguration *tc = nullptr;
|
||||
QHash<QString, QuickTestConfiguration *> foundProFiles;
|
||||
|
||||
for (int row = 0, count = childCount(); row < count; ++row) {
|
||||
@@ -219,39 +269,10 @@ QList<TestConfiguration *> QuickTestTreeItem::getSelectedTestConfigurations() co
|
||||
continue;
|
||||
|
||||
// named Quick Tests
|
||||
switch (child->checked()) {
|
||||
case Qt::Unchecked:
|
||||
continue;
|
||||
case Qt::Checked:
|
||||
case Qt::PartiallyChecked:
|
||||
default:
|
||||
QStringList testFunctions;
|
||||
int grandChildCount = child->childCount();
|
||||
for (int grandChildRow = 0; grandChildRow < grandChildCount; ++grandChildRow) {
|
||||
const TestTreeItem *grandChild = child->childItem(grandChildRow);
|
||||
if (grandChild->checked() != Qt::Checked || grandChild->type() != TestFunctionOrSet)
|
||||
continue;
|
||||
testFunctions << child->name() + "::" + grandChild->name();
|
||||
testConfigurationFromCheckState(child, foundProFiles);
|
||||
}
|
||||
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 ( ; it != end; ++it) {
|
||||
|
||||
for (auto it = foundProFiles.begin(), end = foundProFiles.end(); it != end; ++it) {
|
||||
QuickTestConfiguration *config = it.value();
|
||||
if (!config->unnamedOnly())
|
||||
result << config;
|
||||
@@ -327,6 +348,12 @@ bool QuickTestTreeItem::isGroupNodeFor(const TestTreeItem *other) const
|
||||
return TestTreeItem::isGroupNodeFor(other);
|
||||
}
|
||||
|
||||
bool QuickTestTreeItem::removeOnSweepIfEmpty() const
|
||||
{
|
||||
return TestTreeItem::removeOnSweepIfEmpty()
|
||||
|| (type() == TestCase && name().isEmpty()); // remove pseudo item '<unnamed>'
|
||||
}
|
||||
|
||||
TestTreeItem *QuickTestTreeItem::createParentGroupNode() const
|
||||
{
|
||||
if (filePath().isEmpty() || name().isEmpty())
|
||||
|
||||
@@ -48,6 +48,7 @@ public:
|
||||
bool modify(const TestParseResult *result) override;
|
||||
bool lessThan(const TestTreeItem *other, SortMode mode) const override;
|
||||
bool isGroupNodeFor(const TestTreeItem *other) const override;
|
||||
bool removeOnSweepIfEmpty() const override;
|
||||
TestTreeItem *createParentGroupNode() const override;
|
||||
QSet<QString> internalTargets() const override;
|
||||
private:
|
||||
|
||||
@@ -55,13 +55,11 @@ void TestResultDelegate::paint(QPainter *painter, const QStyleOptionViewItem &op
|
||||
{
|
||||
QStyleOptionViewItem opt = option;
|
||||
initStyleOption(&opt, index);
|
||||
painter->save();
|
||||
|
||||
QFontMetrics fm(opt.font);
|
||||
QBrush background;
|
||||
QColor foreground;
|
||||
|
||||
const QAbstractItemView *view = qobject_cast<const QAbstractItemView *>(opt.widget);
|
||||
const bool selected = opt.state & QStyle::State_Selected;
|
||||
|
||||
if (selected) {
|
||||
@@ -71,10 +69,14 @@ void TestResultDelegate::paint(QPainter *painter, const QStyleOptionViewItem &op
|
||||
background = opt.palette.window().color();
|
||||
foreground = opt.palette.text().color();
|
||||
}
|
||||
|
||||
auto resultFilterModel = qobject_cast<const TestResultFilterModel *>(index.model());
|
||||
if (!resultFilterModel)
|
||||
return;
|
||||
painter->save();
|
||||
painter->fillRect(opt.rect, background);
|
||||
painter->setPen(foreground);
|
||||
|
||||
TestResultFilterModel *resultFilterModel = static_cast<TestResultFilterModel *>(view->model());
|
||||
LayoutPositions positions(opt, resultFilterModel);
|
||||
const TestResult *testResult = resultFilterModel->testResult(index);
|
||||
QTC_ASSERT(testResult, painter->restore();return);
|
||||
|
||||
@@ -56,7 +56,7 @@ private:
|
||||
class LayoutPositions
|
||||
{
|
||||
public:
|
||||
LayoutPositions(QStyleOptionViewItem &options, TestResultFilterModel *filterModel)
|
||||
LayoutPositions(QStyleOptionViewItem &options, const TestResultFilterModel *filterModel)
|
||||
: m_totalWidth(options.rect.width()),
|
||||
m_top(options.rect.top()),
|
||||
m_bottom(options.rect.bottom())
|
||||
|
||||
@@ -106,9 +106,9 @@ QVariant TestTreeItem::data(int /*column*/, int role) const
|
||||
bool TestTreeItem::setData(int /*column*/, const QVariant &data, int role)
|
||||
{
|
||||
if (role == Qt::CheckStateRole) {
|
||||
Qt::CheckState old = checked();
|
||||
setChecked((Qt::CheckState)data.toInt());
|
||||
return checked() != old;
|
||||
Qt::CheckState old = m_checked;
|
||||
m_checked = (Qt::CheckState)data.toInt();
|
||||
return m_checked != old;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -168,34 +168,6 @@ bool TestTreeItem::modifyLineAndColumn(const TestParseResult *result)
|
||||
return hasBeenModified;
|
||||
}
|
||||
|
||||
void TestTreeItem::setChecked(const Qt::CheckState checkState)
|
||||
{
|
||||
switch (m_type) {
|
||||
case TestDataTag: {
|
||||
m_checked = (checkState == Qt::Unchecked ? Qt::Unchecked : Qt::Checked);
|
||||
if (auto parent = parentItem())
|
||||
parent->revalidateCheckState();
|
||||
break;
|
||||
}
|
||||
case Root:
|
||||
case GroupNode:
|
||||
case TestFunctionOrSet:
|
||||
case TestCase: {
|
||||
Qt::CheckState usedState = (checkState == Qt::Unchecked ? Qt::Unchecked : Qt::Checked);
|
||||
for (int row = 0, count = childCount(); row < count; ++row)
|
||||
childItem(row)->setChecked(usedState);
|
||||
m_checked = usedState;
|
||||
if (m_type != Root) {
|
||||
if (auto parent = parentItem())
|
||||
parent->revalidateCheckState();
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Qt::CheckState TestTreeItem::checked() const
|
||||
{
|
||||
switch (m_type) {
|
||||
@@ -327,41 +299,6 @@ QSet<QString> TestTreeItem::internalTargets() const
|
||||
return targets;
|
||||
}
|
||||
|
||||
void TestTreeItem::revalidateCheckState()
|
||||
{
|
||||
const Type ttiType = type();
|
||||
if (ttiType != TestCase && ttiType != TestFunctionOrSet && ttiType != Root && ttiType != GroupNode)
|
||||
return;
|
||||
if (childCount() == 0) // can this happen? (we're calling revalidateCS() on parentItem()
|
||||
return;
|
||||
bool foundChecked = false;
|
||||
bool foundUnchecked = false;
|
||||
bool foundPartiallyChecked = false;
|
||||
for (int row = 0, count = childCount(); row < count; ++row) {
|
||||
TestTreeItem *child = childItem(row);
|
||||
switch (child->type()) {
|
||||
case TestDataFunction:
|
||||
case TestSpecialFunction:
|
||||
continue;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
foundChecked |= (child->checked() == Qt::Checked);
|
||||
foundUnchecked |= (child->checked() == Qt::Unchecked);
|
||||
foundPartiallyChecked |= (child->checked() == Qt::PartiallyChecked);
|
||||
if (foundPartiallyChecked || (foundChecked && foundUnchecked)) {
|
||||
m_checked = Qt::PartiallyChecked;
|
||||
if (ttiType == TestFunctionOrSet || ttiType == TestCase || ttiType == GroupNode)
|
||||
parentItem()->revalidateCheckState();
|
||||
return;
|
||||
}
|
||||
}
|
||||
m_checked = (foundUnchecked ? Qt::Unchecked : Qt::Checked);
|
||||
if (ttiType == TestFunctionOrSet || ttiType == TestCase || ttiType == GroupNode)
|
||||
parentItem()->revalidateCheckState();
|
||||
}
|
||||
|
||||
inline bool TestTreeItem::modifyFilePath(const QString &filePath)
|
||||
{
|
||||
if (m_filePath != filePath) {
|
||||
|
||||
@@ -89,12 +89,12 @@ public:
|
||||
unsigned column() const { return m_column; }
|
||||
QString proFile() const { return m_proFile; }
|
||||
void setProFile(const QString &proFile) { m_proFile = proFile; }
|
||||
virtual void setChecked(const Qt::CheckState checked);
|
||||
virtual Qt::CheckState checked() const;
|
||||
Type type() const { return m_type; }
|
||||
void markForRemoval(bool mark);
|
||||
void markForRemovalRecursively(bool mark);
|
||||
virtual void markForRemovalRecursively(const QString &filePath);
|
||||
virtual bool removeOnSweepIfEmpty() const { return m_type == GroupNode; }
|
||||
bool markedForRemoval() const { return m_status == MarkedForRemoval; }
|
||||
bool newlyAdded() const { return m_status == NewlyAdded; }
|
||||
TestTreeItem *parentItem() const;
|
||||
@@ -123,7 +123,6 @@ protected:
|
||||
const QString &file);
|
||||
|
||||
private:
|
||||
void revalidateCheckState();
|
||||
bool modifyFilePath(const QString &filePath);
|
||||
bool modifyName(const QString &name);
|
||||
|
||||
@@ -143,7 +142,7 @@ private:
|
||||
QString m_proFile;
|
||||
Status m_status = NewlyAdded;
|
||||
|
||||
friend class TestTreeModel; // grant access to (private) revalidateCheckState()
|
||||
friend class TestTreeModel; // grant access to (protected) findChildBy()
|
||||
};
|
||||
|
||||
class TestCodeLocationAndType
|
||||
|
||||
@@ -108,22 +108,19 @@ bool TestTreeModel::setData(const QModelIndex &index, const QVariant &value, int
|
||||
if (item && item->setData(index.column(), value, role)) {
|
||||
emit dataChanged(index, index);
|
||||
if (role == Qt::CheckStateRole) {
|
||||
switch (item->type()) {
|
||||
case TestTreeItem::Root:
|
||||
case TestTreeItem::GroupNode:
|
||||
case TestTreeItem::TestCase:
|
||||
if (item->childCount() > 0)
|
||||
emit dataChanged(index.child(0, 0), index.child(item->childCount() - 1, 0));
|
||||
break;
|
||||
case TestTreeItem::TestFunctionOrSet:
|
||||
emit dataChanged(index.parent(), index.parent());
|
||||
break;
|
||||
default: // avoid warning regarding unhandled enum member
|
||||
break;
|
||||
Qt::CheckState checked = item->checked();
|
||||
if (item->hasChildren() && checked != Qt::PartiallyChecked) {
|
||||
// handle the new checkstate for children as well...
|
||||
for (Utils::TreeItem *child : *item) {
|
||||
const QModelIndex &idx = indexForItem(child);
|
||||
setData(idx, checked ? Qt::Checked : Qt::Unchecked, Qt::CheckStateRole);
|
||||
}
|
||||
}
|
||||
if (item->parent() != rootItem() && item->parentItem()->checked() != checked)
|
||||
revalidateCheckState(item->parentItem()); // handle parent too
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -254,10 +251,14 @@ bool TestTreeModel::sweepChildren(TestTreeItem *item)
|
||||
|
||||
if (child->type() != TestTreeItem::Root && child->markedForRemoval()) {
|
||||
destroyItem(child);
|
||||
item->revalidateCheckState();
|
||||
revalidateCheckState(item);
|
||||
hasChanged = true;
|
||||
} else if (child->hasChildren()) {
|
||||
hasChanged |= sweepChildren(child);
|
||||
if (!child->hasChildren() && child->removeOnSweepIfEmpty()) {
|
||||
destroyItem(child);
|
||||
revalidateCheckState(item);
|
||||
}
|
||||
} else {
|
||||
hasChanged |= child->newlyAdded();
|
||||
}
|
||||
@@ -281,6 +282,50 @@ void TestTreeModel::insertItemInParent(TestTreeItem *item, TestTreeItem *root, b
|
||||
}
|
||||
}
|
||||
parentNode->appendChild(item);
|
||||
if (item->checked() != parentNode->checked())
|
||||
revalidateCheckState(parentNode);
|
||||
}
|
||||
|
||||
void TestTreeModel::revalidateCheckState(TestTreeItem *item)
|
||||
{
|
||||
QTC_ASSERT(item, return);
|
||||
|
||||
const TestTreeItem::Type type = item->type();
|
||||
if (type == TestTreeItem::TestSpecialFunction || type == TestTreeItem::TestDataFunction
|
||||
|| type == TestTreeItem::TestDataTag) {
|
||||
return;
|
||||
}
|
||||
const Qt::CheckState oldState = (Qt::CheckState)item->data(0, Qt::CheckStateRole).toInt();
|
||||
Qt::CheckState newState = Qt::Checked;
|
||||
bool foundChecked = false;
|
||||
bool foundUnchecked = false;
|
||||
bool foundPartiallyChecked = false;
|
||||
for (int row = 0, count = item->childCount(); row < count; ++row) {
|
||||
TestTreeItem *child = item->childItem(row);
|
||||
switch (child->type()) {
|
||||
case TestTreeItem::TestDataFunction:
|
||||
case TestTreeItem::TestSpecialFunction:
|
||||
continue;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
foundChecked |= (child->checked() == Qt::Checked);
|
||||
foundUnchecked |= (child->checked() == Qt::Unchecked);
|
||||
foundPartiallyChecked |= (child->checked() == Qt::PartiallyChecked);
|
||||
if (foundPartiallyChecked || (foundChecked && foundUnchecked)) {
|
||||
newState = Qt::PartiallyChecked;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (newState != Qt::PartiallyChecked)
|
||||
newState = foundUnchecked ? Qt::Unchecked : Qt::Checked;
|
||||
if (oldState != newState) {
|
||||
item->setData(0, newState, Qt::CheckStateRole);
|
||||
emit dataChanged(item->index(), item->index());
|
||||
if (item->parent() != rootItem() && item->parentItem()->checked() != newState)
|
||||
revalidateCheckState(item->parentItem());
|
||||
}
|
||||
}
|
||||
|
||||
void TestTreeModel::onParseResultReady(const TestParseResultPtr result)
|
||||
@@ -321,12 +366,6 @@ void TestTreeModel::handleParseResult(const TestParseResult *result, TestTreeIte
|
||||
QTC_ASSERT(newItem, return);
|
||||
|
||||
insertItemInParent(newItem, parentNode, groupingEnabled);
|
||||
// new items are checked by default - revalidation of parents might be necessary
|
||||
if (parentNode->checked() != Qt::Checked) {
|
||||
parentNode->revalidateCheckState();
|
||||
const QModelIndex &idx = indexForItem(parentNode);
|
||||
emit dataChanged(idx, idx);
|
||||
}
|
||||
}
|
||||
|
||||
void TestTreeModel::removeAllTestItems()
|
||||
@@ -335,7 +374,7 @@ void TestTreeModel::removeAllTestItems()
|
||||
item->removeChildren();
|
||||
TestTreeItem *testTreeItem = static_cast<TestTreeItem *>(item);
|
||||
if (testTreeItem->checked() == Qt::PartiallyChecked)
|
||||
testTreeItem->setChecked(Qt::Checked);
|
||||
testTreeItem->setData(0, Qt::Checked, Qt::CheckStateRole);
|
||||
}
|
||||
emit testTreeModelChanged();
|
||||
}
|
||||
|
||||
@@ -87,8 +87,8 @@ private:
|
||||
void removeTestRootNodes();
|
||||
void removeFiles(const QStringList &files);
|
||||
bool sweepChildren(TestTreeItem *item);
|
||||
static void insertItemInParent(TestTreeItem *item, TestTreeItem *root, bool groupingEnabled);
|
||||
|
||||
void insertItemInParent(TestTreeItem *item, TestTreeItem *root, bool groupingEnabled);
|
||||
void revalidateCheckState(TestTreeItem *item);
|
||||
explicit TestTreeModel(QObject *parent = 0);
|
||||
void setupParsingConnections();
|
||||
|
||||
|
||||
@@ -45,6 +45,13 @@ TestTreeView::TestTreeView(QWidget *parent)
|
||||
Core::ICore::addContextObject(m_context);
|
||||
}
|
||||
|
||||
static void changeCheckStateAll(const Qt::CheckState checkState)
|
||||
{
|
||||
TestTreeModel *model = TestTreeModel::instance();
|
||||
for (int row = 0, count = model->rowCount(); row < count; ++row)
|
||||
model->setData(model->index(row, 0), checkState, Qt::CheckStateRole);
|
||||
}
|
||||
|
||||
void TestTreeView::selectAll()
|
||||
{
|
||||
changeCheckStateAll(Qt::Checked);
|
||||
@@ -55,40 +62,5 @@ void TestTreeView::deselectAll()
|
||||
changeCheckStateAll(Qt::Unchecked);
|
||||
}
|
||||
|
||||
// this avoids the re-evaluation of parent nodes when modifying the child nodes (setData())
|
||||
void TestTreeView::changeCheckStateAll(const Qt::CheckState checkState)
|
||||
{
|
||||
const TestTreeModel *model = TestTreeModel::instance();
|
||||
|
||||
for (int rootRow = 0; rootRow < model->rowCount(rootIndex()); ++rootRow) {
|
||||
QModelIndex currentRootIndex = model->index(rootRow, 0, rootIndex());
|
||||
if (!currentRootIndex.isValid())
|
||||
return;
|
||||
int count = model->rowCount(currentRootIndex);
|
||||
QModelIndex last;
|
||||
for (int classesRow = 0; classesRow < count; ++classesRow) {
|
||||
const QModelIndex classesIndex = model->index(classesRow, 0, currentRootIndex);
|
||||
int funcCount = model->rowCount(classesIndex);
|
||||
TestTreeItem *item = static_cast<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 Autotest
|
||||
|
||||
@@ -45,7 +45,6 @@ public:
|
||||
void deselectAll();
|
||||
|
||||
private:
|
||||
void changeCheckStateAll(const Qt::CheckState checkState);
|
||||
Core::IContext *m_context;
|
||||
};
|
||||
|
||||
|
||||
@@ -368,26 +368,23 @@ QFuture<CppTools::CursorInfo> BackendCommunicator::requestReferences(
|
||||
const FileContainer &fileContainer,
|
||||
quint32 line,
|
||||
quint32 column,
|
||||
QTextDocument *textDocument,
|
||||
const CppTools::SemanticInfo::LocalUseMap &localUses)
|
||||
{
|
||||
const RequestReferencesMessage message(fileContainer, line, column);
|
||||
m_sender->requestReferences(message);
|
||||
|
||||
return m_receiver.addExpectedReferencesMessage(message.ticketNumber(), textDocument,
|
||||
localUses);
|
||||
return m_receiver.addExpectedReferencesMessage(message.ticketNumber(), localUses);
|
||||
}
|
||||
|
||||
QFuture<CppTools::CursorInfo> BackendCommunicator::requestLocalReferences(
|
||||
const FileContainer &fileContainer,
|
||||
quint32 line,
|
||||
quint32 column,
|
||||
QTextDocument *textDocument)
|
||||
quint32 column)
|
||||
{
|
||||
const RequestReferencesMessage message(fileContainer, line, column, true);
|
||||
m_sender->requestReferences(message);
|
||||
|
||||
return m_receiver.addExpectedReferencesMessage(message.ticketNumber(), textDocument);
|
||||
return m_receiver.addExpectedReferencesMessage(message.ticketNumber());
|
||||
}
|
||||
|
||||
QFuture<CppTools::ToolTipInfo> BackendCommunicator::requestToolTip(
|
||||
|
||||
@@ -75,13 +75,11 @@ public:
|
||||
const FileContainer &fileContainer,
|
||||
quint32 line,
|
||||
quint32 column,
|
||||
QTextDocument *textDocument,
|
||||
const LocalUseMap &localUses);
|
||||
QFuture<CppTools::CursorInfo> requestLocalReferences(
|
||||
const FileContainer &fileContainer,
|
||||
quint32 line,
|
||||
quint32 column,
|
||||
QTextDocument *textDocument);
|
||||
quint32 column);
|
||||
QFuture<CppTools::ToolTipInfo> requestToolTip(const FileContainer &fileContainer,
|
||||
quint32 line,
|
||||
quint32 column);
|
||||
|
||||
@@ -101,16 +101,14 @@ void BackendReceiver::deleteProcessorsOfEditorWidget(TextEditor::TextEditorWidge
|
||||
|
||||
QFuture<CppTools::CursorInfo> BackendReceiver::addExpectedReferencesMessage(
|
||||
quint64 ticket,
|
||||
QTextDocument *textDocument,
|
||||
const CppTools::SemanticInfo::LocalUseMap &localUses)
|
||||
{
|
||||
QTC_CHECK(textDocument);
|
||||
QTC_CHECK(!m_referencesTable.contains(ticket));
|
||||
|
||||
QFutureInterface<CppTools::CursorInfo> futureInterface;
|
||||
futureInterface.reportStarted();
|
||||
|
||||
const ReferencesEntry entry{futureInterface, textDocument, localUses};
|
||||
const ReferencesEntry entry{futureInterface, localUses};
|
||||
m_referencesTable.insert(ticket, entry);
|
||||
|
||||
return futureInterface.future();
|
||||
@@ -221,24 +219,17 @@ void BackendReceiver::documentAnnotationsChanged(const DocumentAnnotationsChange
|
||||
}
|
||||
|
||||
static
|
||||
CppTools::CursorInfo::Range toCursorInfoRange(const QTextDocument &textDocument,
|
||||
const SourceRangeContainer &sourceRange)
|
||||
CppTools::CursorInfo::Range toCursorInfoRange(const SourceRangeContainer &sourceRange)
|
||||
{
|
||||
const SourceLocationContainer start = sourceRange.start();
|
||||
const SourceLocationContainer end = sourceRange.end();
|
||||
const unsigned length = end.column() - start.column();
|
||||
|
||||
const QTextBlock block = textDocument.findBlockByNumber(static_cast<int>(start.line()) - 1);
|
||||
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);
|
||||
return CppTools::CursorInfo::Range(start.line(), start.column(), length);
|
||||
}
|
||||
|
||||
static
|
||||
CppTools::CursorInfo toCursorInfo(const QTextDocument &textDocument,
|
||||
const CppTools::SemanticInfo::LocalUseMap &localUses,
|
||||
CppTools::CursorInfo toCursorInfo(const CppTools::SemanticInfo::LocalUseMap &localUses,
|
||||
const ReferencesMessage &message)
|
||||
{
|
||||
CppTools::CursorInfo result;
|
||||
@@ -246,7 +237,7 @@ CppTools::CursorInfo toCursorInfo(const QTextDocument &textDocument,
|
||||
|
||||
result.areUseRangesForLocalVariable = message.isLocalVariable();
|
||||
for (const SourceRangeContainer &reference : references)
|
||||
result.useRanges.append(toCursorInfoRange(textDocument, reference));
|
||||
result.useRanges.append(toCursorInfoRange(reference));
|
||||
|
||||
result.useRanges.reserve(references.size());
|
||||
result.localUses = localUses;
|
||||
@@ -284,8 +275,7 @@ void BackendReceiver::references(const ReferencesMessage &message)
|
||||
if (futureInterface.isCanceled())
|
||||
return; // Editor document closed or a new request was issued making this result outdated.
|
||||
|
||||
QTC_ASSERT(entry.textDocument, return);
|
||||
futureInterface.reportResult(toCursorInfo(*entry.textDocument, entry.localUses, message));
|
||||
futureInterface.reportResult(toCursorInfo(entry.localUses, message));
|
||||
futureInterface.reportFinished();
|
||||
}
|
||||
|
||||
|
||||
@@ -56,7 +56,6 @@ public:
|
||||
|
||||
QFuture<CppTools::CursorInfo>
|
||||
addExpectedReferencesMessage(quint64 ticket,
|
||||
QTextDocument *textDocument,
|
||||
const CppTools::SemanticInfo::LocalUseMap &localUses
|
||||
= CppTools::SemanticInfo::LocalUseMap());
|
||||
QFuture<CppTools::SymbolInfo> addExpectedRequestFollowSymbolMessage(quint64 ticket);
|
||||
@@ -82,13 +81,10 @@ private:
|
||||
struct ReferencesEntry {
|
||||
ReferencesEntry() = default;
|
||||
ReferencesEntry(QFutureInterface<CppTools::CursorInfo> futureInterface,
|
||||
QTextDocument *textDocument,
|
||||
const CppTools::SemanticInfo::LocalUseMap &localUses)
|
||||
: futureInterface(futureInterface)
|
||||
, textDocument(textDocument)
|
||||
, localUses(localUses) {}
|
||||
QFutureInterface<CppTools::CursorInfo> futureInterface;
|
||||
QPointer<QTextDocument> textDocument;
|
||||
CppTools::SemanticInfo::LocalUseMap localUses;
|
||||
};
|
||||
QHash<quint64, ReferencesEntry> m_referencesTable;
|
||||
|
||||
@@ -559,7 +559,8 @@ ClangCompletionAssistProcessor::extractLineColumn(int position)
|
||||
int line = -1, column = -1;
|
||||
::Utils::Text::convertPosition(m_interface->textDocument(), position, &line, &column);
|
||||
const QTextBlock block = m_interface->textDocument()->findBlock(position);
|
||||
column += ClangCodeModel::Utils::extraUtf8CharsShift(block.text(), column) + 1;
|
||||
const QString stringOnTheLeft = block.text().left(column);
|
||||
column = stringOnTheLeft.toUtf8().size() + 1; // '+ 1' is for 1-based columns
|
||||
return {line, column};
|
||||
}
|
||||
|
||||
|
||||
@@ -64,8 +64,7 @@ int positionInText(QTextDocument *textDocument,
|
||||
{
|
||||
auto textBlock = textDocument->findBlockByNumber(
|
||||
static_cast<int>(sourceLocationContainer.line()) - 1);
|
||||
int column = static_cast<int>(sourceLocationContainer.column()) - 1;
|
||||
column -= ClangCodeModel::Utils::extraUtf8CharsShift(textBlock.text(), column);
|
||||
const int column = static_cast<int>(sourceLocationContainer.column()) - 1;
|
||||
return textBlock.position() + column;
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "clangdiagnostictooltipwidget.h"
|
||||
#include "clangfixitoperation.h"
|
||||
#include "clangfixitoperationsextractor.h"
|
||||
#include "clangmodelmanagersupport.h"
|
||||
#include "clangtokeninfosreporter.h"
|
||||
#include "clangprojectsettings.h"
|
||||
#include "clangutils.h"
|
||||
@@ -66,6 +67,12 @@
|
||||
namespace ClangCodeModel {
|
||||
namespace Internal {
|
||||
|
||||
static ClangProjectSettings &getProjectSettings(ProjectExplorer::Project *project)
|
||||
{
|
||||
QTC_CHECK(project);
|
||||
return ModelManagerSupportClang::instance()->projectSettings(project);
|
||||
}
|
||||
|
||||
ClangEditorDocumentProcessor::ClangEditorDocumentProcessor(
|
||||
BackendCommunicator &communicator,
|
||||
TextEditor::TextDocument *document)
|
||||
@@ -174,6 +181,11 @@ void ClangEditorDocumentProcessor::clearProjectPart()
|
||||
m_projectPart.clear();
|
||||
}
|
||||
|
||||
Core::Id ClangEditorDocumentProcessor::diagnosticConfigId() const
|
||||
{
|
||||
return m_diagnosticConfigId;
|
||||
}
|
||||
|
||||
void ClangEditorDocumentProcessor::updateCodeWarnings(
|
||||
const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics,
|
||||
const ClangBackEnd::DiagnosticContainer &firstHeaderErrorDiagnostic,
|
||||
@@ -331,20 +343,19 @@ ClangEditorDocumentProcessor::cursorInfo(const CppTools::CursorInfoParams ¶m
|
||||
{
|
||||
int line, column;
|
||||
convertPosition(params.textCursor, &line, &column);
|
||||
++column; // for 1-based columns
|
||||
|
||||
if (!isCursorOnIdentifier(params.textCursor))
|
||||
return defaultCursorInfoFuture();
|
||||
|
||||
const QTextBlock block = params.textCursor.document()->findBlockByNumber(line - 1);
|
||||
column += ClangCodeModel::Utils::extraUtf8CharsShift(block.text(), column);
|
||||
const QString stringOnTheLeft = block.text().left(column);
|
||||
column = stringOnTheLeft.toUtf8().size() + 1; // '+ 1' is for 1-based columns
|
||||
const CppTools::SemanticInfo::LocalUseMap localUses
|
||||
= CppTools::BuiltinCursorInfo::findLocalUses(params.semanticInfo.doc, line, column);
|
||||
|
||||
return m_communicator.requestReferences(simpleFileContainer(),
|
||||
static_cast<quint32>(line),
|
||||
static_cast<quint32>(column),
|
||||
textDocument(),
|
||||
localUses);
|
||||
}
|
||||
|
||||
@@ -361,8 +372,7 @@ QFuture<CppTools::CursorInfo> ClangEditorDocumentProcessor::requestLocalReferenc
|
||||
|
||||
return m_communicator.requestLocalReferences(simpleFileContainer(),
|
||||
static_cast<quint32>(line),
|
||||
static_cast<quint32>(column),
|
||||
textDocument());
|
||||
static_cast<quint32>(column));
|
||||
}
|
||||
|
||||
QFuture<CppTools::SymbolInfo>
|
||||
@@ -437,6 +447,7 @@ public:
|
||||
}
|
||||
|
||||
const QStringList &options() const { return m_options; }
|
||||
const Core::Id &diagnosticConfigId() const { return m_diagnosticConfigId; }
|
||||
|
||||
private:
|
||||
void addLanguageOptions()
|
||||
@@ -458,21 +469,28 @@ private:
|
||||
void addDiagnosticOptions()
|
||||
{
|
||||
if (m_projectPart.project) {
|
||||
ClangProjectSettings projectSettings(m_projectPart.project);
|
||||
ClangProjectSettings &projectSettings = getProjectSettings(m_projectPart.project);
|
||||
if (!projectSettings.useGlobalConfig()) {
|
||||
const Core::Id warningConfigId = projectSettings.warningConfigId();
|
||||
const CppTools::ClangDiagnosticConfigsModel configsModel(
|
||||
CppTools::codeModelSettings()->clangCustomDiagnosticConfigs());
|
||||
if (configsModel.hasConfigWithId(warningConfigId)) {
|
||||
m_options.append(
|
||||
configsModel.configWithId(warningConfigId).commandLineWarnings());
|
||||
addDiagnosticOptionsForConfig(configsModel.configWithId(warningConfigId));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_options.append(
|
||||
CppTools::codeModelSettings()->clangDiagnosticConfig().commandLineWarnings());
|
||||
addDiagnosticOptionsForConfig(CppTools::codeModelSettings()->clangDiagnosticConfig());
|
||||
}
|
||||
|
||||
void addDiagnosticOptionsForConfig(const CppTools::ClangDiagnosticConfig &diagnosticConfig)
|
||||
{
|
||||
m_diagnosticConfigId = diagnosticConfig.id();
|
||||
|
||||
m_options.append(diagnosticConfig.clangOptions());
|
||||
addClangTidyOptions(diagnosticConfig.clangTidyChecks());
|
||||
addClazyOptions(diagnosticConfig.clazyChecks());
|
||||
}
|
||||
|
||||
void addXclangArg(const QString &argName, const QString &argValue = QString())
|
||||
@@ -485,24 +503,22 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
void addTidyOptions()
|
||||
void addClangTidyOptions(const QString &checks)
|
||||
{
|
||||
const QString tidyChecks = CppTools::codeModelSettings()->tidyChecks();
|
||||
if (tidyChecks.isEmpty())
|
||||
if (checks.isEmpty())
|
||||
return;
|
||||
|
||||
addXclangArg("-add-plugin", "clang-tidy");
|
||||
addXclangArg("-plugin-arg-clang-tidy", "-checks='-*" + tidyChecks + "'");
|
||||
addXclangArg("-plugin-arg-clang-tidy", "-checks='-*" + checks + "'");
|
||||
}
|
||||
|
||||
void addClazyOptions()
|
||||
void addClazyOptions(const QString &checks)
|
||||
{
|
||||
const QString clazyChecks = CppTools::codeModelSettings()->clazyChecks();
|
||||
if (clazyChecks.isEmpty())
|
||||
if (checks.isEmpty())
|
||||
return;
|
||||
|
||||
addXclangArg("-add-plugin", "clang-lazy");
|
||||
addXclangArg("-plugin-arg-clang-lazy", clazyChecks);
|
||||
addXclangArg("-plugin-arg-clang-lazy", checks);
|
||||
|
||||
// NOTE: we already use -isystem for all include paths to make libclang skip diagnostics for
|
||||
// all of them. That means that ignore-included-files will not change anything unless we decide
|
||||
@@ -515,10 +531,7 @@ private:
|
||||
if (!m_projectPart.project)
|
||||
m_options.append(ClangProjectSettings::globalCommandLineOptions());
|
||||
else
|
||||
m_options.append(ClangProjectSettings{m_projectPart.project}.commandLineOptions());
|
||||
|
||||
addTidyOptions();
|
||||
addClazyOptions();
|
||||
m_options.append(getProjectSettings(m_projectPart.project).commandLineOptions());
|
||||
}
|
||||
|
||||
void addPrecompiledHeaderOptions()
|
||||
@@ -541,6 +554,7 @@ private:
|
||||
const QString &m_filePath;
|
||||
const CppTools::ProjectPart &m_projectPart;
|
||||
|
||||
Core::Id m_diagnosticConfigId;
|
||||
QStringList m_options;
|
||||
};
|
||||
} // namespace
|
||||
@@ -563,6 +577,7 @@ void ClangEditorDocumentProcessor::registerTranslationUnitForEditor(
|
||||
}
|
||||
|
||||
const FileOptionsBuilder fileOptions(filePath(), projectPart);
|
||||
m_diagnosticConfigId = fileOptions.diagnosticConfigId();
|
||||
m_communicator.registerTranslationUnitsForEditor(
|
||||
{fileContainerWithOptionsAndDocumentContent(projectPart, fileOptions.options())});
|
||||
ClangCodeModel::Utils::setLastSentDocumentRevision(filePath(), revision());
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "clangdiagnosticmanager.h"
|
||||
#include "clangeditordocumentparser.h"
|
||||
|
||||
#include <coreplugin/id.h>
|
||||
#include <cpptools/builtineditordocumentprocessor.h>
|
||||
#include <cpptools/semantichighlighter.h>
|
||||
|
||||
@@ -67,6 +68,8 @@ public:
|
||||
CppTools::ProjectPart::Ptr projectPart() const;
|
||||
void clearProjectPart();
|
||||
|
||||
Core::Id diagnosticConfigId() const;
|
||||
|
||||
void updateCodeWarnings(const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics,
|
||||
const ClangBackEnd::DiagnosticContainer &firstHeaderErrorDiagnostic,
|
||||
uint documentRevision);
|
||||
@@ -120,6 +123,7 @@ private:
|
||||
BackendCommunicator &m_communicator;
|
||||
QSharedPointer<ClangEditorDocumentParser> m_parser;
|
||||
CppTools::ProjectPart::Ptr m_projectPart;
|
||||
Core::Id m_diagnosticConfigId;
|
||||
bool m_isProjectFile = false;
|
||||
QFutureWatcher<void> m_parserWatcher;
|
||||
QTimer m_updateTranslationUnitTimer;
|
||||
|
||||
@@ -133,6 +133,9 @@ void ClangHoverHandler::identifyMatch(TextEditorWidget *editorWidget,
|
||||
m_reportPriority = report;
|
||||
m_futureWatcher.reset(new QFutureWatcher<CppTools::ToolTipInfo>());
|
||||
QObject::connect(m_futureWatcher.data(), &QFutureWatcherBase::finished, [this]() {
|
||||
if (m_futureWatcher->isCanceled())
|
||||
m_reportPriority(Priority_None);
|
||||
else
|
||||
processToolTipInfo(m_futureWatcher->result());
|
||||
});
|
||||
m_futureWatcher->setFuture(future);
|
||||
|
||||
@@ -30,22 +30,27 @@
|
||||
#include "clangutils.h"
|
||||
#include "clangfollowsymbol.h"
|
||||
#include "clanghoverhandler.h"
|
||||
#include "clangprojectsettings.h"
|
||||
#include "clangrefactoringengine.h"
|
||||
#include "clangcurrentdocumentfilter.h"
|
||||
|
||||
#include <coreplugin/editormanager/editormanager.h>
|
||||
#include <cpptools/cppcodemodelsettings.h>
|
||||
#include <cpptools/cppfollowsymbolundercursor.h>
|
||||
#include <cpptools/cppmodelmanager.h>
|
||||
#include <cpptools/cpptoolsreuse.h>
|
||||
#include <cpptools/editordocumenthandle.h>
|
||||
#include <cpptools/projectinfo.h>
|
||||
|
||||
#include <texteditor/quickfix.h>
|
||||
|
||||
#include <projectexplorer/project.h>
|
||||
#include <projectexplorer/session.h>
|
||||
|
||||
#include <clangsupport/cmbregisterprojectsforeditormessage.h>
|
||||
#include <clangsupport/filecontainer.h>
|
||||
#include <clangsupport/projectpartcontainer.h>
|
||||
#include <utils/algorithm.h>
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
#include <QCoreApplication>
|
||||
@@ -100,11 +105,22 @@ ModelManagerSupportClang::ModelManagerSupportClang()
|
||||
connect(modelManager, &CppTools::CppModelManager::projectPartsRemoved,
|
||||
this, &ModelManagerSupportClang::onProjectPartsRemoved);
|
||||
|
||||
auto *sessionManager = ProjectExplorer::SessionManager::instance();
|
||||
connect(sessionManager, &ProjectExplorer::SessionManager::projectAdded,
|
||||
this, &ModelManagerSupportClang::onProjectAdded);
|
||||
connect(sessionManager, &ProjectExplorer::SessionManager::aboutToRemoveProject,
|
||||
this, &ModelManagerSupportClang::onAboutToRemoveProject);
|
||||
|
||||
CppTools::CppCodeModelSettings *settings = CppTools::codeModelSettings().data();
|
||||
connect(settings, &CppTools::CppCodeModelSettings::clangDiagnosticConfigsInvalidated,
|
||||
this, &ModelManagerSupportClang::onDiagnosticConfigsInvalidated);
|
||||
|
||||
m_communicator.registerFallbackProjectPart();
|
||||
}
|
||||
|
||||
ModelManagerSupportClang::~ModelManagerSupportClang()
|
||||
{
|
||||
QTC_CHECK(m_projectSettings.isEmpty());
|
||||
m_instance = 0;
|
||||
}
|
||||
|
||||
@@ -336,6 +352,52 @@ void ModelManagerSupportClang::onTextMarkContextMenuRequested(TextEditor::TextEd
|
||||
}
|
||||
}
|
||||
|
||||
using ClangEditorDocumentProcessors = QVector<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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
QVector<ClangEditorDocumentProcessor *> result;
|
||||
|
||||
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;
|
||||
return ::Utils::filtered(clangProcessors(), [projectPartIds](ClangEditorDocumentProcessor *p) {
|
||||
return p->hasProjectPart() && projectPartIds.contains(p->projectPart()->id());
|
||||
});
|
||||
}
|
||||
|
||||
void ModelManagerSupportClang::unregisterTranslationUnitsWithProjectParts(
|
||||
@@ -398,6 +464,12 @@ QString ModelManagerSupportClang::dummyUiHeaderOnDiskPath(const QString &filePat
|
||||
return m_uiHeaderOnDiskManager.mapPath(filePath);
|
||||
}
|
||||
|
||||
ClangProjectSettings &ModelManagerSupportClang::projectSettings(
|
||||
ProjectExplorer::Project *project) const
|
||||
{
|
||||
return *m_projectSettings.value(project);
|
||||
}
|
||||
|
||||
QString ModelManagerSupportClang::dummyUiHeaderOnDiskDirPath() const
|
||||
{
|
||||
return m_uiHeaderOnDiskManager.directoryPath();
|
||||
|
||||
@@ -40,7 +40,10 @@ class QMenu;
|
||||
class QWidget;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace Core { class IDocument; }
|
||||
namespace Core {
|
||||
class IDocument;
|
||||
class Id;
|
||||
} // namespace Core
|
||||
namespace TextEditor { class TextEditorWidget; }
|
||||
namespace CppTools {
|
||||
class FollowSymbolInterface;
|
||||
@@ -50,6 +53,8 @@ class RefactoringEngineInterface;
|
||||
namespace ClangCodeModel {
|
||||
namespace Internal {
|
||||
|
||||
class ClangProjectSettings;
|
||||
|
||||
class ModelManagerSupportClang:
|
||||
public QObject,
|
||||
public CppTools::ModelManagerSupport
|
||||
@@ -71,6 +76,8 @@ public:
|
||||
QString dummyUiHeaderOnDiskDirPath() const;
|
||||
QString dummyUiHeaderOnDiskPath(const QString &filePath) const;
|
||||
|
||||
ClangProjectSettings &projectSettings(ProjectExplorer::Project *project) const;
|
||||
|
||||
static ModelManagerSupportClang *instance();
|
||||
|
||||
private:
|
||||
@@ -93,9 +100,14 @@ private:
|
||||
int lineNumber,
|
||||
QMenu *menu);
|
||||
|
||||
void onProjectAdded(ProjectExplorer::Project *project);
|
||||
void onAboutToRemoveProject(ProjectExplorer::Project *project);
|
||||
|
||||
void onProjectPartsUpdated(ProjectExplorer::Project *project);
|
||||
void onProjectPartsRemoved(const QStringList &projectPartIds);
|
||||
|
||||
void onDiagnosticConfigsInvalidated(const QVector<Core::Id> &configIds);
|
||||
|
||||
void unregisterTranslationUnitsWithProjectParts(const QStringList &projectPartIds);
|
||||
|
||||
void connectTextDocumentToTranslationUnit(TextEditor::TextDocument *textDocument);
|
||||
@@ -111,6 +123,8 @@ private:
|
||||
ClangCompletionAssistProvider m_completionAssistProvider;
|
||||
std::unique_ptr<CppTools::FollowSymbolInterface> m_followSymbol;
|
||||
std::unique_ptr<CppTools::RefactoringEngineInterface> m_refactoringEngine;
|
||||
|
||||
QHash<ProjectExplorer::Project *, ClangProjectSettings *> m_projectSettings;
|
||||
};
|
||||
|
||||
class ModelManagerSupportProviderClang : public CppTools::ModelManagerSupportProvider
|
||||
|
||||
@@ -42,6 +42,25 @@ static QString warningConfigIdKey()
|
||||
static QString customCommandLineKey()
|
||||
{ return QLatin1String("ClangCodeModel.CustomCommandLineKey"); }
|
||||
|
||||
static bool useGlobalConfigFromSettings(ProjectExplorer::Project *project)
|
||||
{
|
||||
const QVariant useGlobalConfigVariant = project->namedSettings(useGlobalConfigKey());
|
||||
return useGlobalConfigVariant.isValid() ? useGlobalConfigVariant.toBool() : true;
|
||||
}
|
||||
|
||||
static Core::Id warningConfigIdFromSettings(ProjectExplorer::Project *project)
|
||||
{
|
||||
return Core::Id::fromSetting(project->namedSettings(warningConfigIdKey()));
|
||||
}
|
||||
|
||||
static QStringList customCommandLineFromSettings(ProjectExplorer::Project *project)
|
||||
{
|
||||
QStringList options = project->namedSettings(customCommandLineKey()).toStringList();
|
||||
if (options.empty())
|
||||
options = ClangProjectSettings::globalCommandLineOptions();
|
||||
return options;
|
||||
}
|
||||
|
||||
ClangProjectSettings::ClangProjectSettings(ProjectExplorer::Project *project)
|
||||
: m_project(project)
|
||||
{
|
||||
@@ -88,23 +107,27 @@ void ClangProjectSettings::setCommandLineOptions(const QStringList &options)
|
||||
|
||||
void ClangProjectSettings::load()
|
||||
{
|
||||
const QVariant useGlobalConfigVariant = m_project->namedSettings(useGlobalConfigKey());
|
||||
const bool useGlobalConfig = useGlobalConfigVariant.isValid()
|
||||
? useGlobalConfigVariant.toBool()
|
||||
: true;
|
||||
|
||||
setUseGlobalConfig(useGlobalConfig);
|
||||
setWarningConfigId(Core::Id::fromSetting(m_project->namedSettings(warningConfigIdKey())));
|
||||
m_customCommandLineOptions = m_project->namedSettings(customCommandLineKey()).toStringList();
|
||||
if (m_customCommandLineOptions.empty())
|
||||
m_customCommandLineOptions = globalCommandLineOptions();
|
||||
setUseGlobalConfig(useGlobalConfigFromSettings(m_project));
|
||||
setWarningConfigId(warningConfigIdFromSettings(m_project));
|
||||
m_customCommandLineOptions = customCommandLineFromSettings(m_project);
|
||||
}
|
||||
|
||||
void ClangProjectSettings::store()
|
||||
{
|
||||
bool settingsChanged = false;
|
||||
if (useGlobalConfig() != useGlobalConfigFromSettings(m_project))
|
||||
settingsChanged = true;
|
||||
if (warningConfigId() != warningConfigIdFromSettings(m_project))
|
||||
settingsChanged = true;
|
||||
if (commandLineOptions() != customCommandLineFromSettings(m_project))
|
||||
settingsChanged = true;
|
||||
|
||||
m_project->setNamedSettings(useGlobalConfigKey(), useGlobalConfig());
|
||||
m_project->setNamedSettings(warningConfigIdKey(), warningConfigId().toSetting());
|
||||
m_project->setNamedSettings(customCommandLineKey(), m_customCommandLineOptions);
|
||||
|
||||
if (settingsChanged)
|
||||
emit changed();
|
||||
}
|
||||
|
||||
QStringList ClangProjectSettings::globalCommandLineOptions()
|
||||
|
||||
@@ -59,6 +59,9 @@ public:
|
||||
|
||||
static QStringList globalCommandLineOptions();
|
||||
|
||||
signals:
|
||||
void changed();
|
||||
|
||||
private:
|
||||
ProjectExplorer::Project *m_project;
|
||||
bool m_useGlobalConfig = true;
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
#include "clangprojectsettingswidget.h"
|
||||
|
||||
#include "clangmodelmanagersupport.h"
|
||||
#include "clangprojectsettings.h"
|
||||
|
||||
#include <coreplugin/icore.h>
|
||||
@@ -52,7 +53,7 @@ static Core::Id configIdForProject(ClangProjectSettings &projectSettings)
|
||||
}
|
||||
|
||||
ClangProjectSettingsWidget::ClangProjectSettingsWidget(ProjectExplorer::Project *project)
|
||||
: m_projectSettings(project)
|
||||
: m_projectSettings(ModelManagerSupportClang::instance()->projectSettings(project))
|
||||
{
|
||||
m_ui.setupUi(this);
|
||||
|
||||
@@ -76,6 +77,8 @@ ClangProjectSettingsWidget::ClangProjectSettingsWidget(ProjectExplorer::Project
|
||||
connect(m_ui.clangSettings,
|
||||
static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
|
||||
this, &ClangProjectSettingsWidget::onClangSettingsChanged);
|
||||
connect(project, &ProjectExplorer::Project::aboutToSaveSettings,
|
||||
this, &ClangProjectSettingsWidget::onAboutToSaveProjectSettings);
|
||||
|
||||
m_ui.diagnosticConfigurationGroupBox->layout()->addWidget(m_diagnosticConfigWidget);
|
||||
}
|
||||
@@ -86,7 +89,6 @@ void ClangProjectSettingsWidget::onCurrentWarningConfigChanged(const Core::Id &c
|
||||
if (m_projectSettings.useGlobalConfig())
|
||||
return;
|
||||
m_projectSettings.setWarningConfigId(currentConfigId);
|
||||
m_projectSettings.store();
|
||||
}
|
||||
|
||||
void ClangProjectSettingsWidget::onCustomWarningConfigsChanged(
|
||||
@@ -97,7 +99,6 @@ void ClangProjectSettingsWidget::onCustomWarningConfigsChanged(
|
||||
const QSharedPointer<CppTools::CppCodeModelSettings> codeModelSettings
|
||||
= CppTools::codeModelSettings();
|
||||
codeModelSettings->setClangCustomDiagnosticConfigs(customConfigs);
|
||||
codeModelSettings->toSettings(Core::ICore::settings());
|
||||
|
||||
connectToCppCodeModelSettingsChanged();
|
||||
}
|
||||
@@ -115,16 +116,19 @@ void ClangProjectSettingsWidget::onDelayedTemplateParseClicked(bool checked)
|
||||
options.removeAll(QLatin1String{ClangProjectSettings::NoDelayedTemplateParsing});
|
||||
options.append(extraFlag);
|
||||
m_projectSettings.setCommandLineOptions(options);
|
||||
m_projectSettings.store();
|
||||
}
|
||||
|
||||
void ClangProjectSettingsWidget::onClangSettingsChanged(int index)
|
||||
{
|
||||
m_projectSettings.setUseGlobalConfig(index == 0 ? true : false);
|
||||
m_projectSettings.store();
|
||||
syncOtherWidgetsToComboBox();
|
||||
}
|
||||
|
||||
void ClangProjectSettingsWidget::onAboutToSaveProjectSettings()
|
||||
{
|
||||
CppTools::codeModelSettings()->toSettings(Core::ICore::settings());
|
||||
}
|
||||
|
||||
void ClangProjectSettingsWidget::syncOtherWidgetsToComboBox()
|
||||
{
|
||||
const QStringList options = m_projectSettings.commandLineOptions();
|
||||
|
||||
@@ -51,6 +51,7 @@ private:
|
||||
void onCustomWarningConfigsChanged(const CppTools::ClangDiagnosticConfigs &customConfigs);
|
||||
void onDelayedTemplateParseClicked(bool);
|
||||
void onClangSettingsChanged(int index);
|
||||
void onAboutToSaveProjectSettings();
|
||||
void refreshDiagnosticConfigsWidgetFromSettings();
|
||||
void connectToCppCodeModelSettingsChanged();
|
||||
void disconnectFromCppCodeModelSettingsChanged();
|
||||
@@ -58,7 +59,7 @@ private:
|
||||
|
||||
private:
|
||||
Ui::ClangProjectSettingsWidget m_ui;
|
||||
ClangProjectSettings m_projectSettings;
|
||||
ClangProjectSettings &m_projectSettings;
|
||||
QPointer<CppTools::ClangDiagnosticConfigsWidget> m_diagnosticConfigWidget;
|
||||
};
|
||||
|
||||
|
||||
@@ -190,31 +190,5 @@ void setLastSentDocumentRevision(const QString &filePath, uint revision)
|
||||
document->sendTracker().setLastSentRevision(int(revision));
|
||||
}
|
||||
|
||||
// CLANG-UPGRADE-CHECK: Workaround still needed?
|
||||
// Remove once clang reports correct columns for lines with multi-byte utf8.
|
||||
int extraUtf8CharsShift(const QString &str, int column)
|
||||
{
|
||||
int shift = 0;
|
||||
const QByteArray byteArray = str.toUtf8();
|
||||
for (int i = 0; i < qMin(str.length(), column); ++i) {
|
||||
const uchar firstByte = static_cast<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 Clang
|
||||
|
||||
@@ -47,7 +47,5 @@ CppTools::ProjectPart::Ptr projectPartForFileBasedOnProcessor(const QString &fil
|
||||
bool isProjectPartLoaded(const CppTools::ProjectPart::Ptr projectPart);
|
||||
QString projectPartIdForFile(const QString &filePath);
|
||||
|
||||
int extraUtf8CharsShift(const QString &str, int column);
|
||||
|
||||
} // namespace Utils
|
||||
} // namespace Clang
|
||||
|
||||
@@ -460,7 +460,6 @@ int ServerModeReader::calculateProgress(const int minRange, const int min, const
|
||||
void ServerModeReader::extractCodeModelData(const QVariantMap &data)
|
||||
{
|
||||
const QVariantList configs = data.value("configurations").toList();
|
||||
QTC_CHECK(configs.count() == 1); // FIXME: Support several configurations!
|
||||
for (const QVariant &c : configs) {
|
||||
const QVariantMap &cData = c.toMap();
|
||||
extractConfigurationData(cData);
|
||||
@@ -842,6 +841,11 @@ void ServerModeReader::addFileGroups(ProjectNode *targetRoot,
|
||||
{
|
||||
QList<FileNode *> toList;
|
||||
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) {
|
||||
const QList<FileName> newSources = Utils::filtered(f->sources, [&alreadyListed](const Utils::FileName &fn) {
|
||||
const int count = alreadyListed.count();
|
||||
|
||||
@@ -93,6 +93,8 @@ public:
|
||||
virtual QFuture<SymbolInfo> requestFollowSymbol(int line, int column) = 0;
|
||||
virtual QFuture<ToolTipInfo> toolTipInfo(const QByteArray &codecName, int line, int column);
|
||||
|
||||
QString filePath() const { return m_filePath; }
|
||||
|
||||
public:
|
||||
using HeaderErrorDiagnosticWidgetCreator = std::function<QWidget*()>;
|
||||
|
||||
@@ -117,7 +119,6 @@ protected:
|
||||
BaseEditorDocumentParser::UpdateParams updateParams);
|
||||
|
||||
// Convenience
|
||||
QString filePath() const { return m_filePath; }
|
||||
unsigned revision() const { return static_cast<unsigned>(m_textDocument->revision()); }
|
||||
QTextDocument *textDocument() const { return m_textDocument; }
|
||||
|
||||
|
||||
@@ -47,14 +47,14 @@ void ClangDiagnosticConfig::setDisplayName(const QString &displayName)
|
||||
m_displayName = displayName;
|
||||
}
|
||||
|
||||
QStringList ClangDiagnosticConfig::commandLineWarnings() const
|
||||
QStringList ClangDiagnosticConfig::clangOptions() const
|
||||
{
|
||||
return m_commandLineWarnings;
|
||||
return m_clangOptions;
|
||||
}
|
||||
|
||||
void ClangDiagnosticConfig::setCommandLineWarnings(const QStringList &warnings)
|
||||
void ClangDiagnosticConfig::setClangOptions(const QStringList &options)
|
||||
{
|
||||
m_commandLineWarnings = warnings;
|
||||
m_clangOptions = options;
|
||||
}
|
||||
|
||||
bool ClangDiagnosticConfig::isReadOnly() const
|
||||
@@ -71,8 +71,35 @@ bool ClangDiagnosticConfig::operator==(const ClangDiagnosticConfig &other) const
|
||||
{
|
||||
return m_id == other.m_id
|
||||
&& m_displayName == other.m_displayName
|
||||
&& m_commandLineWarnings == other.m_commandLineWarnings
|
||||
&& m_clangOptions == other.m_clangOptions
|
||||
&& m_clangTidyChecks == other.m_clangTidyChecks
|
||||
&& m_clazyChecks == other.m_clazyChecks
|
||||
&& m_isReadOnly == other.m_isReadOnly;
|
||||
}
|
||||
|
||||
bool ClangDiagnosticConfig::operator!=(const ClangDiagnosticConfig &other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
QString ClangDiagnosticConfig::clangTidyChecks() const
|
||||
{
|
||||
return m_clangTidyChecks;
|
||||
}
|
||||
|
||||
void ClangDiagnosticConfig::setClangTidyChecks(const QString &checks)
|
||||
{
|
||||
m_clangTidyChecks = checks;
|
||||
}
|
||||
|
||||
QString ClangDiagnosticConfig::clazyChecks() const
|
||||
{
|
||||
return m_clazyChecks;
|
||||
}
|
||||
|
||||
void ClangDiagnosticConfig::setClazyChecks(const QString &checks)
|
||||
{
|
||||
m_clazyChecks = checks;
|
||||
}
|
||||
|
||||
} // namespace CppTools
|
||||
|
||||
@@ -43,18 +43,27 @@ public:
|
||||
QString displayName() const;
|
||||
void setDisplayName(const QString &displayName);
|
||||
|
||||
QStringList commandLineWarnings() const;
|
||||
void setCommandLineWarnings(const QStringList &commandLineWarnings);
|
||||
QStringList clangOptions() const;
|
||||
void setClangOptions(const QStringList &options);
|
||||
|
||||
QString clangTidyChecks() const;
|
||||
void setClangTidyChecks(const QString &checks);
|
||||
|
||||
QString clazyChecks() const;
|
||||
void setClazyChecks(const QString &checks);
|
||||
|
||||
bool isReadOnly() const;
|
||||
void setIsReadOnly(bool isReadOnly);
|
||||
|
||||
bool operator==(const ClangDiagnosticConfig &other) const;
|
||||
bool operator!=(const ClangDiagnosticConfig &other) const;
|
||||
|
||||
private:
|
||||
Core::Id m_id;
|
||||
QString m_displayName;
|
||||
QStringList m_commandLineWarnings;
|
||||
QStringList m_clangOptions;
|
||||
QString m_clangTidyChecks;
|
||||
QString m_clazyChecks;
|
||||
bool m_isReadOnly = false;
|
||||
};
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ static void addConfigForQuestionableConstructs(ClangDiagnosticConfigsModel &mode
|
||||
config.setDisplayName(QCoreApplication::translate("ClangDiagnosticConfigsModel",
|
||||
"Warnings for questionable constructs"));
|
||||
config.setIsReadOnly(true);
|
||||
config.setCommandLineWarnings(QStringList{
|
||||
config.setClangOptions(QStringList{
|
||||
QStringLiteral("-Wall"),
|
||||
QStringLiteral("-Wextra"),
|
||||
} + commonWarnings());
|
||||
@@ -60,7 +60,7 @@ static void addConfigForPedanticWarnings(ClangDiagnosticConfigsModel &model)
|
||||
config.setDisplayName(QCoreApplication::translate("ClangDiagnosticConfigsModel",
|
||||
"Pedantic Warnings"));
|
||||
config.setIsReadOnly(true);
|
||||
config.setCommandLineWarnings(QStringList{QStringLiteral("-Wpedantic")} + commonWarnings());
|
||||
config.setClangOptions(QStringList{QStringLiteral("-Wpedantic")} + commonWarnings());
|
||||
|
||||
model.appendOrUpdate(config);
|
||||
}
|
||||
@@ -72,7 +72,7 @@ static void addConfigForAlmostEveryWarning(ClangDiagnosticConfigsModel &model)
|
||||
config.setDisplayName(QCoreApplication::translate("ClangDiagnosticConfigsModel",
|
||||
"Warnings for almost everything"));
|
||||
config.setIsReadOnly(true);
|
||||
config.setCommandLineWarnings(QStringList{
|
||||
config.setClangOptions(QStringList{
|
||||
QStringLiteral("-Weverything"),
|
||||
QStringLiteral("-Wno-c++98-compat"),
|
||||
QStringLiteral("-Wno-c++98-compat-pedantic"),
|
||||
@@ -158,6 +158,23 @@ ClangDiagnosticConfigsModel::displayNameWithBuiltinIndication(const ClangDiagnos
|
||||
: config.displayName();
|
||||
}
|
||||
|
||||
QVector<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
|
||||
{
|
||||
return Utils::indexOf(m_diagnosticConfigs, [&](const ClangDiagnosticConfig &config) {
|
||||
|
||||
@@ -29,6 +29,8 @@
|
||||
|
||||
#include "clangdiagnosticconfig.h"
|
||||
|
||||
#include <QVector>
|
||||
|
||||
namespace CppTools {
|
||||
|
||||
class CPPTOOLS_EXPORT ClangDiagnosticConfigsModel
|
||||
@@ -47,11 +49,11 @@ public:
|
||||
ClangDiagnosticConfigs configs() const;
|
||||
bool hasConfigWithId(const Core::Id &id) const;
|
||||
const ClangDiagnosticConfig &configWithId(const Core::Id &id) const;
|
||||
int indexOfConfig(const Core::Id &id) const;
|
||||
|
||||
static QString displayNameWithBuiltinIndication(const ClangDiagnosticConfig &config);
|
||||
|
||||
private:
|
||||
int indexOfConfig(const Core::Id &id) const;
|
||||
static QVector<Core::Id> changedOrRemovedConfigs(const ClangDiagnosticConfigs &oldConfigs,
|
||||
const ClangDiagnosticConfigs &newConfigs);
|
||||
|
||||
private:
|
||||
ClangDiagnosticConfigs m_diagnosticConfigs;
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
|
||||
#include "clangdiagnosticconfigswidget.h"
|
||||
#include "ui_clangdiagnosticconfigswidget.h"
|
||||
#include "ui_clazychecks.h"
|
||||
#include "ui_tidychecks.h"
|
||||
|
||||
#include <utils/algorithm.h>
|
||||
#include <utils/qtcassert.h>
|
||||
@@ -45,6 +47,7 @@ ClangDiagnosticConfigsWidget::ClangDiagnosticConfigsWidget(
|
||||
, m_diagnosticConfigsModel(diagnosticConfigsModel)
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
setupPluginsWidgets();
|
||||
|
||||
connectConfigChooserCurrentIndex();
|
||||
connect(m_ui->copyButton, &QPushButton::clicked,
|
||||
@@ -108,6 +111,18 @@ void ClangDiagnosticConfigsWidget::onRemoveButtonClicked()
|
||||
syncConfigChooserToModel();
|
||||
}
|
||||
|
||||
void ClangDiagnosticConfigsWidget::onClangTidyItemChanged(QListWidgetItem *item)
|
||||
{
|
||||
const QString prefix = item->text();
|
||||
ClangDiagnosticConfig config = currentConfig();
|
||||
QString checks = config.clangTidyChecks();
|
||||
item->checkState() == Qt::Checked
|
||||
? checks.append(',' + prefix)
|
||||
: checks.remove(',' + prefix);
|
||||
config.setClangTidyChecks(checks);
|
||||
updateConfig(config);
|
||||
}
|
||||
|
||||
static bool isAcceptedWarningOption(const QString &option)
|
||||
{
|
||||
return option == "-w"
|
||||
@@ -162,10 +177,8 @@ void ClangDiagnosticConfigsWidget::onDiagnosticOptionsEdited()
|
||||
|
||||
// Commit valid changes
|
||||
ClangDiagnosticConfig updatedConfig = currentConfig();
|
||||
updatedConfig.setCommandLineWarnings(normalizedOptions);
|
||||
|
||||
m_diagnosticConfigsModel.appendOrUpdate(updatedConfig);
|
||||
emit customConfigsChanged(customConfigs());
|
||||
updatedConfig.setClangOptions(normalizedOptions);
|
||||
updateConfig(updatedConfig);
|
||||
}
|
||||
|
||||
void ClangDiagnosticConfigsWidget::syncWidgetsToModel(const Core::Id &configToSelect)
|
||||
@@ -213,12 +226,74 @@ void ClangDiagnosticConfigsWidget::syncOtherWidgetsToComboBox()
|
||||
// Update main button row
|
||||
m_ui->removeButton->setEnabled(!config.isReadOnly());
|
||||
|
||||
// Update child widgets
|
||||
// Update Text Edit
|
||||
const QString options = m_notAcceptedOptions.contains(config.id())
|
||||
? m_notAcceptedOptions.value(config.id())
|
||||
: config.commandLineWarnings().join(QLatin1Char(' '));
|
||||
: config.clangOptions().join(QLatin1Char(' '));
|
||||
setDiagnosticOptions(options);
|
||||
m_ui->diagnosticOptionsTextEdit->setReadOnly(config.isReadOnly());
|
||||
|
||||
syncClangTidyWidgets(config);
|
||||
syncClazyWidgets(config);
|
||||
}
|
||||
|
||||
void ClangDiagnosticConfigsWidget::syncClangTidyWidgets(const ClangDiagnosticConfig &config)
|
||||
{
|
||||
disconnectClangTidyItemChanged();
|
||||
|
||||
const QString tidyChecks = config.clangTidyChecks();
|
||||
for (int row = 0; row < m_tidyChecks->checksList->count(); ++row) {
|
||||
QListWidgetItem *item = m_tidyChecks->checksList->item(row);
|
||||
|
||||
Qt::ItemFlags flags = item->flags();
|
||||
flags |= Qt::ItemIsUserCheckable;
|
||||
if (config.isReadOnly())
|
||||
flags &= ~Qt::ItemIsEnabled;
|
||||
else
|
||||
flags |= Qt::ItemIsEnabled;
|
||||
item->setFlags(flags);
|
||||
|
||||
if (tidyChecks.indexOf(item->text()) != -1)
|
||||
item->setCheckState(Qt::Checked);
|
||||
else
|
||||
item->setCheckState(Qt::Unchecked);
|
||||
}
|
||||
|
||||
connectClangTidyItemChanged();
|
||||
}
|
||||
|
||||
void ClangDiagnosticConfigsWidget::syncClazyWidgets(const ClangDiagnosticConfig &config)
|
||||
{
|
||||
const QString clazyChecks = config.clazyChecks();
|
||||
if (clazyChecks.isEmpty())
|
||||
m_clazyChecks->clazyLevel->setCurrentIndex(0);
|
||||
else
|
||||
m_clazyChecks->clazyLevel->setCurrentText(clazyChecks);
|
||||
m_clazyChecksWidget->setEnabled(!config.isReadOnly());
|
||||
}
|
||||
|
||||
void ClangDiagnosticConfigsWidget::setClazyLevelDescription(int index)
|
||||
{
|
||||
// Levels descriptions are taken from https://github.com/KDE/clazy
|
||||
static const QString levelDescriptions[] {
|
||||
QString(),
|
||||
tr("Very stable checks, 99.99% safe, no false-positives."),
|
||||
tr("Similar to level 0, but sometimes (rarely) there might be\n"
|
||||
"some false-positives."),
|
||||
tr("Sometimes has false-positives (20-30%)."),
|
||||
tr("Not always correct, possibly very noisy, might require\n"
|
||||
"a knowledgeable developer to review, might have a very big\n"
|
||||
"rate of false-positives, might have bugs.")
|
||||
};
|
||||
|
||||
QTC_ASSERT(m_clazyChecks, return);
|
||||
m_clazyChecks->levelDescription->setText(levelDescriptions[static_cast<unsigned>(index)]);
|
||||
}
|
||||
|
||||
void ClangDiagnosticConfigsWidget::updateConfig(const ClangDiagnosticConfig &config)
|
||||
{
|
||||
m_diagnosticConfigsModel.appendOrUpdate(config);
|
||||
emit customConfigsChanged(customConfigs());
|
||||
}
|
||||
|
||||
bool ClangDiagnosticConfigsWidget::isConfigChooserEmpty() const
|
||||
@@ -264,6 +339,18 @@ void ClangDiagnosticConfigsWidget::updateValidityWidgets(const QString &errorMes
|
||||
m_ui->validationResultLabel->setStyleSheet(styleSheet);
|
||||
}
|
||||
|
||||
void ClangDiagnosticConfigsWidget::connectClangTidyItemChanged()
|
||||
{
|
||||
connect(m_tidyChecks->checksList, &QListWidget::itemChanged,
|
||||
this, &ClangDiagnosticConfigsWidget::onClangTidyItemChanged);
|
||||
}
|
||||
|
||||
void ClangDiagnosticConfigsWidget::disconnectClangTidyItemChanged()
|
||||
{
|
||||
disconnect(m_tidyChecks->checksList, &QListWidget::itemChanged,
|
||||
this, &ClangDiagnosticConfigsWidget::onClangTidyItemChanged);
|
||||
}
|
||||
|
||||
void ClangDiagnosticConfigsWidget::connectConfigChooserCurrentIndex()
|
||||
{
|
||||
connect(m_ui->configChooserComboBox,
|
||||
@@ -314,4 +401,31 @@ void ClangDiagnosticConfigsWidget::refresh(
|
||||
syncWidgetsToModel(configToSelect);
|
||||
}
|
||||
|
||||
void ClangDiagnosticConfigsWidget::setupPluginsWidgets()
|
||||
{
|
||||
m_clazyChecks.reset(new CppTools::Ui::ClazyChecks);
|
||||
m_clazyChecksWidget = new QWidget();
|
||||
m_clazyChecks->setupUi(m_clazyChecksWidget);
|
||||
connect(m_clazyChecks->clazyLevel,
|
||||
static_cast<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
|
||||
|
||||
@@ -33,9 +33,17 @@
|
||||
#include <QHash>
|
||||
#include <QWidget>
|
||||
|
||||
#include <memory>
|
||||
|
||||
QT_FORWARD_DECLARE_CLASS(QListWidgetItem)
|
||||
|
||||
namespace CppTools {
|
||||
|
||||
namespace Ui { class ClangDiagnosticConfigsWidget; }
|
||||
namespace Ui {
|
||||
class ClangDiagnosticConfigsWidget;
|
||||
class ClazyChecks;
|
||||
class TidyChecks;
|
||||
}
|
||||
|
||||
class CPPTOOLS_EXPORT ClangDiagnosticConfigsWidget : public QWidget
|
||||
{
|
||||
@@ -59,15 +67,23 @@ signals:
|
||||
void customConfigsChanged(const CppTools::ClangDiagnosticConfigs &customConfigs);
|
||||
|
||||
private:
|
||||
void setupPluginsWidgets();
|
||||
|
||||
void onCurrentConfigChanged(int);
|
||||
void onCopyButtonClicked();
|
||||
void onRemoveButtonClicked();
|
||||
void onClangTidyItemChanged(QListWidgetItem *item);
|
||||
|
||||
void onDiagnosticOptionsEdited();
|
||||
|
||||
void syncWidgetsToModel(const Core::Id &configToSelect = Core::Id());
|
||||
void syncConfigChooserToModel(const Core::Id &configToSelect = Core::Id());
|
||||
void syncOtherWidgetsToComboBox();
|
||||
void syncClangTidyWidgets(const ClangDiagnosticConfig &config);
|
||||
void syncClazyWidgets(const ClangDiagnosticConfig &config);
|
||||
|
||||
void setClazyLevelDescription(int index);
|
||||
void updateConfig(const CppTools::ClangDiagnosticConfig &config);
|
||||
|
||||
bool isConfigChooserEmpty() const;
|
||||
const ClangDiagnosticConfig ¤tConfig() const;
|
||||
@@ -75,6 +91,9 @@ private:
|
||||
void setDiagnosticOptions(const QString &options);
|
||||
void updateValidityWidgets(const QString &errorMessage);
|
||||
|
||||
void connectClangTidyItemChanged();
|
||||
void disconnectClangTidyItemChanged();
|
||||
|
||||
void connectConfigChooserCurrentIndex();
|
||||
void disconnectConfigChooserCurrentIndex();
|
||||
void connectDiagnosticOptionsChanged();
|
||||
@@ -84,6 +103,12 @@ private:
|
||||
Ui::ClangDiagnosticConfigsWidget *m_ui;
|
||||
ClangDiagnosticConfigsModel m_diagnosticConfigsModel;
|
||||
QHash<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
|
||||
|
||||
@@ -93,6 +93,9 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTabWidget" name="pluginChecksTabs"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
|
||||
@@ -27,8 +27,10 @@
|
||||
|
||||
#include <coreplugin/icore.h>
|
||||
|
||||
#include <projectexplorer/project.h>
|
||||
#include <projectexplorer/projectexplorerconstants.h>
|
||||
|
||||
#include <utils/fileutils.h>
|
||||
#include <utils/qtcassert.h>
|
||||
#include <utils/qtcfallthrough.h>
|
||||
|
||||
@@ -37,6 +39,8 @@
|
||||
|
||||
namespace CppTools {
|
||||
|
||||
static constexpr char SYSTEM_INCLUDE_PREFIX[] = "-isystem";
|
||||
|
||||
CompilerOptionsBuilder::CompilerOptionsBuilder(const ProjectPart &projectPart,
|
||||
const QString &clangVersion,
|
||||
const QString &clangResourceDirectory)
|
||||
@@ -119,10 +123,23 @@ void CompilerOptionsBuilder::enableExceptions()
|
||||
add(QLatin1String("-fexceptions"));
|
||||
}
|
||||
|
||||
static Utils::FileName absoluteDirectory(const QString &filePath)
|
||||
{
|
||||
return Utils::FileName::fromString(QFileInfo(filePath + '/').absolutePath());
|
||||
}
|
||||
|
||||
static Utils::FileName projectTopLevelDirectory(const ProjectPart &projectPart)
|
||||
{
|
||||
if (!projectPart.project)
|
||||
return Utils::FileName();
|
||||
return projectPart.project->projectDirectory();
|
||||
}
|
||||
|
||||
void CompilerOptionsBuilder::addHeaderPathOptions()
|
||||
{
|
||||
typedef ProjectPartHeaderPath HeaderPath;
|
||||
const QString defaultPrefix = includeDirOption();
|
||||
const Utils::FileName projectDirectory = projectTopLevelDirectory(m_projectPart);
|
||||
|
||||
QStringList result;
|
||||
|
||||
@@ -134,6 +151,7 @@ void CompilerOptionsBuilder::addHeaderPathOptions()
|
||||
continue;
|
||||
|
||||
QString prefix;
|
||||
Utils::FileName path;
|
||||
switch (headerPath.type) {
|
||||
case HeaderPath::FrameworkPath:
|
||||
prefix = QLatin1String("-F");
|
||||
@@ -141,7 +159,11 @@ void CompilerOptionsBuilder::addHeaderPathOptions()
|
||||
default: // This shouldn't happen, but let's be nice..:
|
||||
// intentional fall-through:
|
||||
case HeaderPath::IncludePath:
|
||||
path = absoluteDirectory(headerPath.path);
|
||||
if (path == projectDirectory || path.isChildOf(projectDirectory))
|
||||
prefix = defaultPrefix;
|
||||
else
|
||||
prefix = SYSTEM_INCLUDE_PREFIX;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -409,7 +431,7 @@ void CompilerOptionsBuilder::addDefineFunctionMacrosMsvc()
|
||||
|
||||
QString CompilerOptionsBuilder::includeDirOption() const
|
||||
{
|
||||
return QLatin1String("-isystem");
|
||||
return QLatin1String("-I");
|
||||
}
|
||||
|
||||
QByteArray CompilerOptionsBuilder::macroOption(const ProjectExplorer::Macro ¯o) const
|
||||
@@ -506,7 +528,7 @@ void CompilerOptionsBuilder::addPredefinedHeaderPathsOptions()
|
||||
void CompilerOptionsBuilder::addClangIncludeFolder()
|
||||
{
|
||||
QTC_CHECK(!m_clangVersion.isEmpty());
|
||||
add(includeDirOption());
|
||||
add(SYSTEM_INCLUDE_PREFIX);
|
||||
add(clangIncludeDirectory());
|
||||
}
|
||||
|
||||
|
||||
@@ -55,6 +55,12 @@ static QString clangDiagnosticConfigsArrayDisplayNameKey()
|
||||
static QString clangDiagnosticConfigsArrayWarningsKey()
|
||||
{ return QLatin1String("diagnosticOptions"); }
|
||||
|
||||
static QString clangDiagnosticConfigsArrayClangTidyChecksKey()
|
||||
{ return QLatin1String("clangTidyChecks"); }
|
||||
|
||||
static QString clangDiagnosticConfigsArrayClazyChecksKey()
|
||||
{ return QLatin1String("clazyChecks"); }
|
||||
|
||||
static QString pchUsageKey()
|
||||
{ return QLatin1String(Constants::CPPTOOLS_MODEL_MANAGER_PCH_USAGE); }
|
||||
|
||||
@@ -67,15 +73,12 @@ static QString skipIndexingBigFilesKey()
|
||||
static QString indexerFileSizeLimitKey()
|
||||
{ return QLatin1String(Constants::CPPTOOLS_INDEXER_FILE_SIZE_LIMIT); }
|
||||
|
||||
static QString tidyChecksKey()
|
||||
{ return QLatin1String(Constants::CPPTOOLS_TIDY_CHECKS); }
|
||||
|
||||
static QString clazyChecksKey()
|
||||
{ return QLatin1String(Constants::CPPTOOLS_CLAZY_CHECKS); }
|
||||
|
||||
void CppCodeModelSettings::fromSettings(QSettings *s)
|
||||
static ClangDiagnosticConfigs customDiagnosticConfigsFromSettings(QSettings *s)
|
||||
{
|
||||
s->beginGroup(QLatin1String(Constants::CPPTOOLS_SETTINGSGROUP));
|
||||
QTC_ASSERT(s->group() == QLatin1String(Constants::CPPTOOLS_SETTINGSGROUP),
|
||||
return ClangDiagnosticConfigs());
|
||||
|
||||
ClangDiagnosticConfigs configs;
|
||||
|
||||
const int size = s->beginReadArray(clangDiagnosticConfigsArrayKey());
|
||||
for (int i = 0; i < size; ++i) {
|
||||
@@ -84,15 +87,30 @@ void CppCodeModelSettings::fromSettings(QSettings *s)
|
||||
ClangDiagnosticConfig config;
|
||||
config.setId(Core::Id::fromSetting(s->value(clangDiagnosticConfigsArrayIdKey())));
|
||||
config.setDisplayName(s->value(clangDiagnosticConfigsArrayDisplayNameKey()).toString());
|
||||
config.setCommandLineWarnings(s->value(clangDiagnosticConfigsArrayWarningsKey()).toStringList());
|
||||
m_clangCustomDiagnosticConfigs.append(config);
|
||||
config.setClangOptions(s->value(clangDiagnosticConfigsArrayWarningsKey()).toStringList());
|
||||
config.setClangTidyChecks(s->value(clangDiagnosticConfigsArrayClangTidyChecksKey()).toString());
|
||||
config.setClazyChecks(s->value(clangDiagnosticConfigsArrayClazyChecksKey()).toString());
|
||||
configs.append(config);
|
||||
}
|
||||
s->endArray();
|
||||
|
||||
const Core::Id diagnosticConfigId = Core::Id::fromSetting(
|
||||
s->value(clangDiagnosticConfigKey(),
|
||||
initialClangDiagnosticConfigId().toSetting()));
|
||||
setClangDiagnosticConfigId(diagnosticConfigId);
|
||||
return configs;
|
||||
}
|
||||
|
||||
static Core::Id clangDiagnosticConfigIdFromSettings(QSettings *s)
|
||||
{
|
||||
QTC_ASSERT(s->group() == QLatin1String(Constants::CPPTOOLS_SETTINGSGROUP), return Core::Id());
|
||||
|
||||
return Core::Id::fromSetting(
|
||||
s->value(clangDiagnosticConfigKey(), initialClangDiagnosticConfigId().toSetting()));
|
||||
}
|
||||
|
||||
void CppCodeModelSettings::fromSettings(QSettings *s)
|
||||
{
|
||||
s->beginGroup(QLatin1String(Constants::CPPTOOLS_SETTINGSGROUP));
|
||||
|
||||
setClangCustomDiagnosticConfigs(customDiagnosticConfigsFromSettings(s));
|
||||
setClangDiagnosticConfigId(clangDiagnosticConfigIdFromSettings(s));
|
||||
|
||||
const QVariant pchUsageVariant = s->value(pchUsageKey(), initialPchUsage());
|
||||
setPCHUsage(static_cast<PCHUsage>(pchUsageVariant.toInt()));
|
||||
@@ -107,11 +125,6 @@ void CppCodeModelSettings::fromSettings(QSettings *s)
|
||||
const QVariant indexerFileSizeLimit = s->value(indexerFileSizeLimitKey(), 5);
|
||||
setIndexerFileSizeLimitInMb(indexerFileSizeLimit.toInt());
|
||||
|
||||
const QVariant tidyChecks = s->value(tidyChecksKey(), QString());
|
||||
setTidyChecks(tidyChecks.toString());
|
||||
const QVariant clazyChecks = s->value(clazyChecksKey(), QString());
|
||||
setClazyChecks(clazyChecks.toString());
|
||||
|
||||
s->endGroup();
|
||||
|
||||
emit changed();
|
||||
@@ -120,6 +133,8 @@ void CppCodeModelSettings::fromSettings(QSettings *s)
|
||||
void CppCodeModelSettings::toSettings(QSettings *s)
|
||||
{
|
||||
s->beginGroup(QLatin1String(Constants::CPPTOOLS_SETTINGSGROUP));
|
||||
const ClangDiagnosticConfigs previousConfigs = customDiagnosticConfigsFromSettings(s);
|
||||
const Core::Id previousConfigId = clangDiagnosticConfigIdFromSettings(s);
|
||||
|
||||
s->beginWriteArray(clangDiagnosticConfigsArrayKey());
|
||||
for (int i = 0, size = m_clangCustomDiagnosticConfigs.size(); i < size; ++i) {
|
||||
@@ -128,7 +143,9 @@ void CppCodeModelSettings::toSettings(QSettings *s)
|
||||
s->setArrayIndex(i);
|
||||
s->setValue(clangDiagnosticConfigsArrayIdKey(), config.id().toSetting());
|
||||
s->setValue(clangDiagnosticConfigsArrayDisplayNameKey(), config.displayName());
|
||||
s->setValue(clangDiagnosticConfigsArrayWarningsKey(), config.commandLineWarnings());
|
||||
s->setValue(clangDiagnosticConfigsArrayWarningsKey(), config.clangOptions());
|
||||
s->setValue(clangDiagnosticConfigsArrayClangTidyChecksKey(), config.clangTidyChecks());
|
||||
s->setValue(clangDiagnosticConfigsArrayClazyChecksKey(), config.clazyChecks());
|
||||
}
|
||||
s->endArray();
|
||||
|
||||
@@ -138,11 +155,18 @@ void CppCodeModelSettings::toSettings(QSettings *s)
|
||||
s->setValue(interpretAmbiguousHeadersAsCHeadersKey(), interpretAmbigiousHeadersAsCHeaders());
|
||||
s->setValue(skipIndexingBigFilesKey(), skipIndexingBigFiles());
|
||||
s->setValue(indexerFileSizeLimitKey(), indexerFileSizeLimitInMb());
|
||||
s->setValue(tidyChecksKey(), tidyChecks());
|
||||
s->setValue(clazyChecksKey(), clazyChecks());
|
||||
|
||||
s->endGroup();
|
||||
|
||||
QVector<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();
|
||||
}
|
||||
|
||||
@@ -212,23 +236,3 @@ void CppCodeModelSettings::setIndexerFileSizeLimitInMb(int sizeInMB)
|
||||
{
|
||||
m_indexerFileSizeLimitInMB = sizeInMB;
|
||||
}
|
||||
|
||||
QString CppCodeModelSettings::tidyChecks() const
|
||||
{
|
||||
return m_tidyChecks;
|
||||
}
|
||||
|
||||
void CppCodeModelSettings::setTidyChecks(QString checks)
|
||||
{
|
||||
m_tidyChecks = checks;
|
||||
}
|
||||
|
||||
QString CppCodeModelSettings::clazyChecks() const
|
||||
{
|
||||
return m_clazyChecks;
|
||||
}
|
||||
|
||||
void CppCodeModelSettings::setClazyChecks(QString checks)
|
||||
{
|
||||
m_clazyChecks = checks;
|
||||
}
|
||||
|
||||
@@ -72,13 +72,8 @@ public:
|
||||
int indexerFileSizeLimitInMb() const;
|
||||
void setIndexerFileSizeLimitInMb(int sizeInMB);
|
||||
|
||||
QString tidyChecks() const;
|
||||
void setTidyChecks(QString checks);
|
||||
|
||||
QString clazyChecks() const;
|
||||
void setClazyChecks(QString checks);
|
||||
|
||||
signals:
|
||||
void clangDiagnosticConfigsInvalidated(const QVector<Core::Id> &configId);
|
||||
void changed();
|
||||
|
||||
private:
|
||||
@@ -88,9 +83,6 @@ private:
|
||||
int m_indexerFileSizeLimitInMB = 5;
|
||||
ClangDiagnosticConfigs m_clangCustomDiagnosticConfigs;
|
||||
Core::Id m_clangDiagnosticConfigId;
|
||||
|
||||
QString m_tidyChecks;
|
||||
QString m_clazyChecks;
|
||||
};
|
||||
|
||||
} // namespace CppTools
|
||||
|
||||
@@ -29,8 +29,6 @@
|
||||
#include "cppmodelmanager.h"
|
||||
#include "cpptoolsconstants.h"
|
||||
#include "ui_cppcodemodelsettingspage.h"
|
||||
#include "ui_clazychecks.h"
|
||||
#include "ui_tidychecks.h"
|
||||
|
||||
#include <coreplugin/icore.h>
|
||||
#include <utils/algorithm.h>
|
||||
@@ -86,79 +84,6 @@ void CppCodeModelSettingsWidget::setupClangCodeModelWidgets()
|
||||
diagnosticConfigsModel,
|
||||
m_settings->clangDiagnosticConfigId());
|
||||
m_ui->clangSettingsGroupBox->layout()->addWidget(m_clangDiagnosticConfigsWidget);
|
||||
|
||||
m_ui->clangPlugins->setEnabled(isClangActive);
|
||||
setupPluginsWidgets();
|
||||
}
|
||||
|
||||
void CppCodeModelSettingsWidget::setupPluginsWidgets()
|
||||
{
|
||||
m_clazyChecks.reset(new CppTools::Ui::ClazyChecks);
|
||||
m_clazyChecksWidget = new QWidget();
|
||||
m_clazyChecks->setupUi(m_clazyChecksWidget);
|
||||
|
||||
m_tidyChecks.reset(new CppTools::Ui::TidyChecks);
|
||||
m_tidyChecksWidget = new QWidget();
|
||||
m_tidyChecks->setupUi(m_tidyChecksWidget);
|
||||
|
||||
m_ui->pluginChecks->addTab(m_tidyChecksWidget, tr("ClangTidy"));
|
||||
m_ui->pluginChecks->addTab(m_clazyChecksWidget, tr("Clazy"));
|
||||
m_ui->pluginChecks->setCurrentIndex(0);
|
||||
|
||||
setupTidyChecks();
|
||||
setupClazyChecks();
|
||||
}
|
||||
|
||||
void CppCodeModelSettingsWidget::setupTidyChecks()
|
||||
{
|
||||
m_currentTidyChecks = m_settings->tidyChecks();
|
||||
for (int row = 0; row < m_tidyChecks->checksList->count(); ++row) {
|
||||
QListWidgetItem *item = m_tidyChecks->checksList->item(row);
|
||||
item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
|
||||
if (m_currentTidyChecks.indexOf(item->text()) != -1)
|
||||
item->setCheckState(Qt::Checked);
|
||||
else
|
||||
item->setCheckState(Qt::Unchecked);
|
||||
}
|
||||
connect(m_tidyChecks->checksList, &QListWidget::itemChanged, [this](QListWidgetItem *item) {
|
||||
const QString prefix = item->text();
|
||||
item->checkState() == Qt::Checked
|
||||
? m_currentTidyChecks.append(',' + prefix)
|
||||
: m_currentTidyChecks.remove(',' + prefix);
|
||||
});
|
||||
}
|
||||
|
||||
void CppCodeModelSettingsWidget::setupClazyChecks()
|
||||
{
|
||||
// Levels descriptions are taken from https://github.com/KDE/clazy
|
||||
static const std::array<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()
|
||||
@@ -192,16 +117,6 @@ bool CppCodeModelSettingsWidget::applyClangCodeModelWidgetsToSettings() const
|
||||
settingsChanged = true;
|
||||
}
|
||||
|
||||
if (m_settings->tidyChecks() != m_currentTidyChecks) {
|
||||
m_settings->setTidyChecks(m_currentTidyChecks);
|
||||
settingsChanged = true;
|
||||
}
|
||||
|
||||
if (m_settings->clazyChecks() != m_currentClazyChecks) {
|
||||
m_settings->setClazyChecks(m_currentClazyChecks);
|
||||
settingsChanged = true;
|
||||
}
|
||||
|
||||
return settingsChanged;
|
||||
}
|
||||
|
||||
|
||||
@@ -32,8 +32,6 @@
|
||||
#include <QPointer>
|
||||
#include <QWidget>
|
||||
|
||||
#include <memory>
|
||||
|
||||
QT_FORWARD_DECLARE_CLASS(QComboBox)
|
||||
QT_FORWARD_DECLARE_CLASS(QSettings)
|
||||
|
||||
@@ -41,11 +39,6 @@ namespace CppTools {
|
||||
|
||||
class ClangDiagnosticConfigsWidget;
|
||||
|
||||
namespace Ui {
|
||||
class ClazyChecks;
|
||||
class TidyChecks;
|
||||
} // namespace Ui
|
||||
|
||||
namespace Internal {
|
||||
|
||||
namespace Ui { class CppCodeModelSettingsPage; }
|
||||
@@ -64,9 +57,6 @@ public:
|
||||
private:
|
||||
void setupGeneralWidgets();
|
||||
void setupClangCodeModelWidgets();
|
||||
void setupPluginsWidgets();
|
||||
void setupTidyChecks();
|
||||
void setupClazyChecks();
|
||||
|
||||
bool applyGeneralWidgetsToSettings() const;
|
||||
bool applyClangCodeModelWidgetsToSettings() const;
|
||||
@@ -75,14 +65,6 @@ private:
|
||||
Ui::CppCodeModelSettingsPage *m_ui = nullptr;
|
||||
QPointer<ClangDiagnosticConfigsWidget> m_clangDiagnosticConfigsWidget;
|
||||
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
|
||||
|
||||
@@ -114,18 +114,6 @@
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3"/>
|
||||
</widget>
|
||||
</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>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
|
||||
@@ -56,8 +56,6 @@ const char CPPTOOLS_INTERPRET_AMBIGIUOUS_HEADERS_AS_C_HEADERS[]
|
||||
= "InterpretAmbiguousHeadersAsCHeaders";
|
||||
const char CPPTOOLS_SKIP_INDEXING_BIG_FILES[] = "SkipIndexingBigFiles";
|
||||
const char CPPTOOLS_INDEXER_FILE_SIZE_LIMIT[] = "IndexerFileSizeLimit";
|
||||
const char CPPTOOLS_TIDY_CHECKS[] = "TidyChecks";
|
||||
const char CPPTOOLS_CLAZY_CHECKS[] = "ClazyChecks";
|
||||
|
||||
const char CPP_CLANG_BUILTIN_CONFIG_ID_EVERYTHING_WITH_EXCEPTIONS[]
|
||||
= "Builtin.EverythingWithExceptions";
|
||||
|
||||
@@ -530,7 +530,7 @@ DebuggerSettings::DebuggerSettings()
|
||||
insertItem(UseToolTipsInBreakpointsView, item);
|
||||
|
||||
item = new SavedAction(this);
|
||||
item->setSettingsKey(debugModeGroup, QLatin1String("UseToolTipsInBreakpointsView"));
|
||||
item->setSettingsKey(debugModeGroup, QLatin1String("UseToolTipsInStackView"));
|
||||
item->setText(tr("Use Tooltips in Stack View when Debugging"));
|
||||
item->setToolTip(tr("<p>Checking this will enable tooltips in the stack "
|
||||
"view during debugging."));
|
||||
|
||||
@@ -365,7 +365,13 @@ void DebuggerRunTool::setBreakOnMain(bool on)
|
||||
|
||||
void DebuggerRunTool::setUseTerminal(bool on)
|
||||
{
|
||||
if (on && !d->terminalRunner && m_runParameters.cppEngineType == GdbEngineType) {
|
||||
// CDB has a built-in console that might be preferred by some.
|
||||
bool useCdbConsole = m_runParameters.cppEngineType == CdbEngineType
|
||||
&& (m_runParameters.startMode == StartInternal
|
||||
|| m_runParameters.startMode == StartExternal)
|
||||
&& boolSetting(UseCdbConsole);
|
||||
|
||||
if (on && !d->terminalRunner && !useCdbConsole) {
|
||||
d->terminalRunner = new TerminalRunner(this);
|
||||
addStartDependency(d->terminalRunner);
|
||||
}
|
||||
@@ -891,15 +897,6 @@ DebuggerRunTool::DebuggerRunTool(RunControl *runControl, Kit *kit, bool allowTer
|
||||
m_engine = createPdbEngine();
|
||||
}
|
||||
}
|
||||
|
||||
if (m_runParameters.cppEngineType == CdbEngineType
|
||||
&& !boolSetting(UseCdbConsole)
|
||||
&& m_runParameters.inferior.runMode == ApplicationLauncher::Console
|
||||
&& (m_runParameters.startMode == StartInternal
|
||||
|| m_runParameters.startMode == StartExternal)) {
|
||||
d->terminalRunner = new TerminalRunner(this);
|
||||
addStartDependency(d->terminalRunner);
|
||||
}
|
||||
}
|
||||
|
||||
DebuggerEngine *DebuggerRunTool::activeEngine() const
|
||||
|
||||
@@ -292,7 +292,6 @@ void LldbEngine::setupEngine()
|
||||
.arg(bp.id().toString()).arg(bp.state()));
|
||||
}
|
||||
}
|
||||
notifyEngineSetupOk();
|
||||
} else {
|
||||
notifyEngineSetupFailed();
|
||||
}
|
||||
|
||||
@@ -88,16 +88,9 @@ bool ModelEditorPlugin::initialize(const QStringList &arguments, QString *errorS
|
||||
Q_UNUSED(errorString);
|
||||
|
||||
d->modelsManager = new ModelsManager(this);
|
||||
addAutoReleasedObject(d->modelsManager);
|
||||
|
||||
d->uiController = new UiController(this);
|
||||
addAutoReleasedObject(d->uiController);
|
||||
|
||||
d->modelFactory = new ModelEditorFactory(d->uiController, this);
|
||||
addAutoReleasedObject(d->modelFactory);
|
||||
|
||||
d->settingsController = new SettingsController(this);
|
||||
addAutoReleasedObject(d->settingsController);
|
||||
|
||||
Core::JsExpander::registerQObjectForJs(QLatin1String("Modeling"), new JsExtension(this));
|
||||
|
||||
|
||||
@@ -63,11 +63,9 @@ AndroidQmakeBuildConfiguration::AndroidQmakeBuildConfiguration(Target *target)
|
||||
: QmakeBuildConfiguration(target)
|
||||
{
|
||||
updateCacheAndEmitEnvironmentChanged();
|
||||
|
||||
auto updateGradle = [this] { AndroidManager::updateGradleProperties(BuildConfiguration::target()); };
|
||||
|
||||
connect(target->project(), &Project::parsingFinished, this, updateGradle);
|
||||
connect(this, &AndroidQmakeBuildConfiguration::enabledChanged, this, updateGradle);
|
||||
connect(target->project(), &Project::parsingFinished, this, [this] {
|
||||
AndroidManager::updateGradleProperties(BuildConfiguration::target());
|
||||
});
|
||||
}
|
||||
|
||||
void AndroidQmakeBuildConfiguration::initialize(const BuildInfo *info)
|
||||
|
||||
@@ -64,6 +64,8 @@ QWidget *ChangeStyleWidgetAction::createWidget(QWidget *parent)
|
||||
QComboBox *comboBox = new QComboBox(parent);
|
||||
comboBox->setToolTip(tr(enabledTooltip));
|
||||
comboBox->addItem("Default");
|
||||
comboBox->addItem("Fusion");
|
||||
comboBox->addItem("Imagine");
|
||||
comboBox->addItem("Material");
|
||||
comboBox->addItem("Universal");
|
||||
comboBox->setEditable(true);
|
||||
|
||||
@@ -164,6 +164,8 @@ const int priorityGoIntoComponent = 40;
|
||||
const int priorityGenericToolBar = 50;
|
||||
const int priorityLast = 60;
|
||||
|
||||
const char addImagesDisplayString[] = QT_TRANSLATE_NOOP("QmlDesignerAddResources", "Image Files");
|
||||
|
||||
} //ComponentCoreConstants
|
||||
|
||||
} //QmlDesigner
|
||||
|
||||
@@ -178,6 +178,16 @@ void DesignerActionManager::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
|
||||
{
|
||||
public:
|
||||
@@ -359,7 +369,7 @@ bool selectionHasSameParentAndInBaseState(const SelectionContext &context)
|
||||
bool isNotInLayout(const SelectionContext &context)
|
||||
{
|
||||
if (selectionNotEmpty(context)) {
|
||||
const ModelNode &selectedModelNode = context.selectedModelNodes().constFirst();
|
||||
const ModelNode selectedModelNode = context.selectedModelNodes().constFirst();
|
||||
ModelNode parentModelNode;
|
||||
|
||||
if (selectedModelNode.hasParentProperty())
|
||||
@@ -983,6 +993,22 @@ void DesignerActionManager::createDefaultDesignerActions()
|
||||
addDesignerAction(new ChangeStyleAction());
|
||||
}
|
||||
|
||||
void DesignerActionManager::createDefaultAddResourceHandler()
|
||||
{
|
||||
registerAddResourceHandler(AddResourceHandler(ComponentCoreConstants::addImagesDisplayString,
|
||||
"*.png",
|
||||
ModelNodeOperations::addImageToProject));
|
||||
registerAddResourceHandler(AddResourceHandler(ComponentCoreConstants::addImagesDisplayString,
|
||||
"*.jpg",
|
||||
ModelNodeOperations::addImageToProject));
|
||||
registerAddResourceHandler(AddResourceHandler(ComponentCoreConstants::addImagesDisplayString,
|
||||
"*.bmp",
|
||||
ModelNodeOperations::addImageToProject));
|
||||
registerAddResourceHandler(AddResourceHandler(ComponentCoreConstants::addImagesDisplayString,
|
||||
"*.svg",
|
||||
ModelNodeOperations::addImageToProject));
|
||||
}
|
||||
|
||||
void DesignerActionManager::addDesignerAction(ActionInterface *newAction)
|
||||
{
|
||||
m_designerActions.append(QSharedPointer<ActionInterface>(newAction));
|
||||
|
||||
@@ -42,6 +42,25 @@ namespace QmlDesigner {
|
||||
|
||||
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
|
||||
{
|
||||
public:
|
||||
@@ -64,6 +83,7 @@ public:
|
||||
QList<ActionInterface* > designerActions() const;
|
||||
|
||||
void createDefaultDesignerActions();
|
||||
void createDefaultAddResourceHandler();
|
||||
DesignerActionManagerView *view();
|
||||
|
||||
DesignerActionToolBar *createToolBar(QWidget *parent = 0) const;
|
||||
@@ -76,9 +96,13 @@ public:
|
||||
DesignerActionManager(const DesignerActionManager&) = delete;
|
||||
DesignerActionManager & operator=(const DesignerActionManager&) = delete;
|
||||
|
||||
QList<AddResourceHandler> addResourceHandler() const;
|
||||
void registerAddResourceHandler(const AddResourceHandler &handler);
|
||||
|
||||
private:
|
||||
QList<QSharedPointer<ActionInterface> > m_designerActions;
|
||||
DesignerActionManagerView *m_designerActionManagerView;
|
||||
QList<AddResourceHandler> m_addResourceHandler;
|
||||
};
|
||||
|
||||
} //QmlDesigner
|
||||
|
||||
@@ -53,7 +53,7 @@ void DesignerActionManagerView::modelAboutToBeDetached(Model *model)
|
||||
|
||||
void DesignerActionManagerView::nodeCreated(const ModelNode &)
|
||||
{
|
||||
setupContext();
|
||||
setupContext(SelectionContext::UpdateMode::Fast);
|
||||
}
|
||||
|
||||
void DesignerActionManagerView::nodeRemoved(const ModelNode &, const NodeAbstractProperty &, AbstractView::PropertyChangeFlags)
|
||||
@@ -63,17 +63,17 @@ void DesignerActionManagerView::nodeRemoved(const ModelNode &, const NodeAbstrac
|
||||
|
||||
void DesignerActionManagerView::nodeAboutToBeReparented(const ModelNode &, const NodeAbstractProperty &, const NodeAbstractProperty &, AbstractView::PropertyChangeFlags)
|
||||
{
|
||||
setupContext();
|
||||
setupContext(SelectionContext::UpdateMode::Fast);
|
||||
}
|
||||
|
||||
void DesignerActionManagerView::nodeReparented(const ModelNode &, const NodeAbstractProperty &, const NodeAbstractProperty &, AbstractView::PropertyChangeFlags)
|
||||
{
|
||||
setupContext();
|
||||
setupContext(SelectionContext::UpdateMode::Fast);
|
||||
}
|
||||
|
||||
void DesignerActionManagerView::propertiesRemoved(const QList<AbstractProperty> &)
|
||||
{
|
||||
setupContext();
|
||||
setupContext(SelectionContext::UpdateMode::Fast);
|
||||
}
|
||||
|
||||
void DesignerActionManagerView::rootNodeTypeChanged(const QString &, int, int)
|
||||
@@ -96,7 +96,7 @@ void DesignerActionManagerView::rewriterEndTransaction()
|
||||
|
||||
void DesignerActionManagerView::currentStateChanged(const ModelNode &)
|
||||
{
|
||||
setupContext();
|
||||
setupContext(SelectionContext::UpdateMode::Fast);
|
||||
}
|
||||
|
||||
void DesignerActionManagerView::selectedNodesChanged(const QList<ModelNode> &selectedNodes, const QList<ModelNode> &)
|
||||
@@ -112,7 +112,7 @@ void DesignerActionManagerView::selectedNodesChanged(const QList<ModelNode> &sel
|
||||
|
||||
void DesignerActionManagerView::nodeOrderChanged(const NodeListProperty &, const ModelNode &, int)
|
||||
{
|
||||
setupContext();
|
||||
setupContext(SelectionContext::UpdateMode::Fast);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
setupContext();
|
||||
setupContext(SelectionContext::UpdateMode::Fast);
|
||||
}
|
||||
|
||||
void DesignerActionManagerView::variantPropertiesChanged(const QList<VariantProperty> &, AbstractView::PropertyChangeFlags propertyChangeFlag)
|
||||
{
|
||||
if (propertyChangeFlag == AbstractView::PropertiesAdded)
|
||||
setupContext();
|
||||
setupContext(SelectionContext::UpdateMode::Fast);
|
||||
else if (hasSingleSelectedModelNode())
|
||||
setupContext();
|
||||
setupContext(SelectionContext::UpdateMode::Fast);
|
||||
}
|
||||
|
||||
void DesignerActionManagerView::bindingPropertiesChanged(const QList<BindingProperty> &, AbstractView::PropertyChangeFlags propertyChangeFlag)
|
||||
{
|
||||
if (propertyChangeFlag == AbstractView::PropertiesAdded)
|
||||
setupContext();
|
||||
setupContext(SelectionContext::UpdateMode::Fast);
|
||||
}
|
||||
|
||||
void DesignerActionManagerView::instancePropertyChanged(const QList<QPair<ModelNode, PropertyName> > &)
|
||||
|
||||
@@ -56,6 +56,10 @@
|
||||
|
||||
#include <qmljseditor/qmljsfindreferences.h>
|
||||
|
||||
#include <projectexplorer/project.h>
|
||||
#include <projectexplorer/projectnodes.h>
|
||||
#include <projectexplorer/projecttree.h>
|
||||
|
||||
#include <utils/algorithm.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
|
||||
|
||||
} //QmlDesigner
|
||||
|
||||
@@ -72,7 +72,7 @@ void addItemToStackedContainer(const SelectionContext &selectionContext);
|
||||
void increaseIndexOfStackedContainer(const SelectionContext &selectionContext);
|
||||
void decreaseIndexOfStackedContainer(const SelectionContext &selectionContext);
|
||||
void addTabBarToStackedContainer(const SelectionContext &selectionContext);
|
||||
|
||||
bool addImageToProject(const QString &fileName, const QString &directory);
|
||||
|
||||
} // namespace ModelNodeOperationso
|
||||
} //QmlDesigner
|
||||
|
||||
@@ -397,7 +397,7 @@ void FormEditorView::changeToCustomTool()
|
||||
int handlingRank = 0;
|
||||
AbstractCustomTool *selectedCustomTool = 0;
|
||||
|
||||
const ModelNode &selectedModelNode = selectedModelNodes().constFirst();
|
||||
const ModelNode selectedModelNode = selectedModelNodes().constFirst();
|
||||
|
||||
foreach (AbstractCustomTool *customTool, m_customToolList) {
|
||||
if (customTool->wantHandleItem(selectedModelNode) > handlingRank) {
|
||||
|
||||
@@ -45,9 +45,11 @@
|
||||
|
||||
#include <coreplugin/coreconstants.h>
|
||||
#include <coreplugin/icore.h>
|
||||
#include <coreplugin/messagebox.h>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QDrag>
|
||||
#include <QFileDialog>
|
||||
#include <QFileInfo>
|
||||
#include <QFileSystemModel>
|
||||
#include <QGridLayout>
|
||||
@@ -76,6 +78,7 @@ ItemLibraryWidget::ItemLibraryWidget(QWidget *parent) :
|
||||
m_itemViewQuickWidget(new QQuickWidget),
|
||||
m_resourcesView(new ItemLibraryResourceView(this)),
|
||||
m_importTagsWidget(new QWidget(this)),
|
||||
m_addResourcesWidget(new QWidget(this)),
|
||||
m_filterFlag(QtBasic)
|
||||
{
|
||||
m_compressionTimer.setInterval(200);
|
||||
@@ -148,7 +151,8 @@ ItemLibraryWidget::ItemLibraryWidget(QWidget *parent) :
|
||||
layout->addWidget(spacer, 1, 0);
|
||||
layout->addWidget(lineEditFrame, 2, 0, 1, 1);
|
||||
layout->addWidget(m_importTagsWidget.data(), 3, 0, 1, 1);
|
||||
layout->addWidget(m_stackedWidget.data(), 4, 0, 1, 1);
|
||||
layout->addWidget(m_addResourcesWidget.data(), 4, 0, 1, 1);
|
||||
layout->addWidget(m_stackedWidget.data(), 5, 0, 1, 1);
|
||||
|
||||
setSearchFilter(QString());
|
||||
|
||||
@@ -164,6 +168,20 @@ ItemLibraryWidget::ItemLibraryWidget(QWidget *parent) :
|
||||
auto *flowLayout = new Utils::FlowLayout(m_importTagsWidget.data());
|
||||
flowLayout->setMargin(4);
|
||||
|
||||
m_addResourcesWidget->setVisible(false);
|
||||
flowLayout = new Utils::FlowLayout(m_addResourcesWidget.data());
|
||||
flowLayout->setMargin(4);
|
||||
auto button = new QToolButton(m_addResourcesWidget.data());
|
||||
auto font = button->font();
|
||||
font.setPixelSize(9);
|
||||
button->setFont(font);
|
||||
button->setIcon(Utils::Icons::PLUS.icon());
|
||||
button->setText(tr("Add New Resources..."));
|
||||
button->setToolTip(tr("Add new resources to project."));
|
||||
button->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
|
||||
flowLayout->addWidget(button);
|
||||
connect(button, &QToolButton::clicked, this, &ItemLibraryWidget::addResources);
|
||||
|
||||
// init the first load of the QML UI elements
|
||||
reloadQmlSource();
|
||||
}
|
||||
@@ -232,12 +250,15 @@ void ItemLibraryWidget::setCurrentIndexOfStackedWidget(int index)
|
||||
if (index == 2) {
|
||||
m_filterLineEdit->setVisible(false);
|
||||
m_importTagsWidget->setVisible(true);
|
||||
m_addResourcesWidget->setVisible(false);
|
||||
} if (index == 1) {
|
||||
m_filterLineEdit->setVisible(true);
|
||||
m_importTagsWidget->setVisible(false);
|
||||
m_addResourcesWidget->setVisible(true);
|
||||
} else {
|
||||
m_filterLineEdit->setVisible(true);
|
||||
m_importTagsWidget->setVisible(true);
|
||||
m_addResourcesWidget->setVisible(false);
|
||||
}
|
||||
|
||||
m_stackedWidget->setCurrentIndex(index);
|
||||
@@ -279,6 +300,7 @@ void ItemLibraryWidget::setupImportTagWidget()
|
||||
button->setIcon(Utils::Icons::PLUS.icon());
|
||||
button->setText(import);
|
||||
button->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
|
||||
button->setToolTip(tr("Add import %1").arg(import));
|
||||
connect(button, &QToolButton::clicked, this, [this, import]() {
|
||||
addPossibleImport(import);
|
||||
});
|
||||
@@ -366,4 +388,47 @@ void ItemLibraryWidget::addPossibleImport(const QString &name)
|
||||
QmlDesignerPlugin::instance()->currentDesignDocument()->updateSubcomponentManager();
|
||||
}
|
||||
|
||||
void ItemLibraryWidget::addResources()
|
||||
{
|
||||
auto document = QmlDesignerPlugin::instance()->currentDesignDocument();
|
||||
|
||||
QTC_ASSERT(document, return);
|
||||
|
||||
QList<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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -96,6 +96,7 @@ private:
|
||||
void removeImport(const QString &name);
|
||||
void addImport(const QString &name, const QString &version);
|
||||
void addPossibleImport(const QString &name);
|
||||
void addResources();
|
||||
|
||||
QTimer m_compressionTimer;
|
||||
QSize m_itemIconSize;
|
||||
@@ -111,6 +112,7 @@ private:
|
||||
QScopedPointer<QQuickWidget> m_itemViewQuickWidget;
|
||||
QScopedPointer<ItemLibraryResourceView> m_resourcesView;
|
||||
QScopedPointer<QWidget> m_importTagsWidget;
|
||||
QScopedPointer<QWidget> m_addResourcesWidget;
|
||||
|
||||
QShortcut *m_qmlSourceUpdateShortcut;
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "navigatorview.h"
|
||||
|
||||
#include <bindingproperty.h>
|
||||
#include <designersettings.h>
|
||||
#include <nodeabstractproperty.h>
|
||||
#include <nodehints.h>
|
||||
#include <nodelistproperty.h>
|
||||
@@ -207,7 +208,8 @@ QVariant NavigatorTreeModel::data(const QModelIndex &index, int role) const
|
||||
} else if (role == Qt::ToolTipRole) {
|
||||
if (currentQmlObjectNode.hasError()) {
|
||||
QString errorString = currentQmlObjectNode.error();
|
||||
if (currentQmlObjectNode.isRootNode())
|
||||
if (DesignerSettings::getValue(DesignerSettingsKey::STANDALONE_MODE).toBool() &&
|
||||
currentQmlObjectNode.isRootNode())
|
||||
errorString.append(QString("\n%1").arg(tr("Changing the setting \"%1\" might solve the issue.").arg(
|
||||
tr("Use QML emulation layer that is built with the selected Qt"))));
|
||||
|
||||
|
||||
@@ -145,7 +145,7 @@ void PropertyEditorContextObject::toogleExportAlias()
|
||||
if (rewriterView->selectedModelNodes().isEmpty())
|
||||
return;
|
||||
|
||||
const ModelNode &selectedNode = rewriterView->selectedModelNodes().constFirst();
|
||||
const ModelNode selectedNode = rewriterView->selectedModelNodes().constFirst();
|
||||
|
||||
if (QmlObjectNode::isValidQmlObjectNode(selectedNode)) {
|
||||
QmlObjectNode objectNode(selectedNode);
|
||||
@@ -208,6 +208,25 @@ void PropertyEditorContextObject::changeTypeName(const QString &typeName)
|
||||
|
||||
}
|
||||
|
||||
void PropertyEditorContextObject::insertKeyframe(const QString &propertyName)
|
||||
{
|
||||
if (!m_model || !m_model->rewriterView())
|
||||
return;
|
||||
|
||||
/* Ideally we should not missuse the rewriterView
|
||||
* If we add more code here we have to forward the property editor view */
|
||||
RewriterView *rewriterView = m_model->rewriterView();
|
||||
|
||||
if (rewriterView->selectedModelNodes().isEmpty())
|
||||
return;
|
||||
|
||||
ModelNode selectedNode = rewriterView->selectedModelNodes().constFirst();
|
||||
|
||||
rewriterView->emitCustomNotification("INSERT_KEYFRAME",
|
||||
{ selectedNode },
|
||||
{ propertyName });
|
||||
}
|
||||
|
||||
int PropertyEditorContextObject::majorVersion() const
|
||||
{
|
||||
return m_majorVersion;
|
||||
@@ -270,6 +289,20 @@ void PropertyEditorContextObject::setMinorVersion(int minorVersion)
|
||||
emit minorVersionChanged();
|
||||
}
|
||||
|
||||
bool PropertyEditorContextObject::hasActiveTimeline() const
|
||||
{
|
||||
return m_setHasActiveTimeline;
|
||||
}
|
||||
|
||||
void PropertyEditorContextObject::setHasActiveTimeline(bool b)
|
||||
{
|
||||
if (b == m_setHasActiveTimeline)
|
||||
return;
|
||||
|
||||
m_setHasActiveTimeline = b;
|
||||
emit hasActiveTimelineChanged();
|
||||
}
|
||||
|
||||
void PropertyEditorContextObject::insertInQmlContext(QQmlContext *context)
|
||||
{
|
||||
m_qmlContext = context;
|
||||
|
||||
@@ -55,6 +55,8 @@ class PropertyEditorContextObject : public QObject
|
||||
|
||||
Q_PROPERTY(bool hasAliasExport READ hasAliasExport NOTIFY hasAliasExportChanged)
|
||||
|
||||
Q_PROPERTY(bool hasActiveTimeline READ hasActiveTimeline NOTIFY hasActiveTimelineChanged)
|
||||
|
||||
Q_PROPERTY(QQmlPropertyMap* backendValues READ backendValues WRITE setBackendValues NOTIFY backendValuesChanged)
|
||||
|
||||
Q_PROPERTY(QQmlComponent* specificQmlComponent READ specificQmlComponent NOTIFY specificQmlComponentChanged)
|
||||
@@ -81,6 +83,7 @@ public:
|
||||
Q_INVOKABLE void toogleExportAlias();
|
||||
|
||||
Q_INVOKABLE void changeTypeName(const QString &typeName);
|
||||
Q_INVOKABLE void insertKeyframe(const QString &propertyName);
|
||||
|
||||
int majorVersion() const;
|
||||
int majorQtQuickVersion() const;
|
||||
@@ -91,6 +94,9 @@ public:
|
||||
int minorVersion() const;
|
||||
void setMinorVersion(int minorVersion);
|
||||
|
||||
bool hasActiveTimeline() const;
|
||||
void setHasActiveTimeline(bool b);
|
||||
|
||||
void insertInQmlContext(QQmlContext *context);
|
||||
QQmlComponent *specificQmlComponent();
|
||||
|
||||
@@ -110,6 +116,7 @@ signals:
|
||||
void minorQtQuickVersionChanged();
|
||||
void specificQmlComponentChanged();
|
||||
void hasAliasExportChanged();
|
||||
void hasActiveTimelineChanged();
|
||||
|
||||
public slots:
|
||||
void setGlobalBaseUrl(const QUrl &newBaseUrl);
|
||||
@@ -153,6 +160,8 @@ private:
|
||||
Model *m_model = nullptr;
|
||||
|
||||
bool m_aliasExport = false;
|
||||
|
||||
bool m_setHasActiveTimeline = false;
|
||||
};
|
||||
|
||||
} //QmlDesigner {
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "propertyeditortransaction.h"
|
||||
#include <qmldesignerconstants.h>
|
||||
#include <qmldesignerplugin.h>
|
||||
#include <qmltimelinemutator.h>
|
||||
|
||||
#include <qmlobjectnode.h>
|
||||
#include <nodemetainfo.h>
|
||||
@@ -328,6 +329,9 @@ void PropertyEditorQmlBackend::setup(const QmlObjectNode &qmlObjectNode, const Q
|
||||
contextObject()->setIsBaseState(qmlObjectNode.isInBaseState());
|
||||
|
||||
contextObject()->setHasAliasExport(qmlObjectNode.isAliasExported());
|
||||
|
||||
contextObject()->setHasActiveTimeline(QmlTimelineMutator::hasActiveTimeline(qmlObjectNode.view()));
|
||||
|
||||
contextObject()->setSelectionChanged(false);
|
||||
|
||||
contextObject()->setSelectionChanged(false);
|
||||
|
||||