Merge remote-tracking branch 'origin/4.10'
Conflicts: CMakeLists.txt tests/unit/unittest/unittest.pro Change-Id: I64296ad31502d9b35012da129a28e9277e9fcf8e
@@ -1,33 +1,18 @@
|
|||||||
cmake_minimum_required(VERSION 3.9)
|
cmake_minimum_required(VERSION 3.9)
|
||||||
|
|
||||||
include(FeatureSummary)
|
|
||||||
|
|
||||||
#BINARY_ARTIFACTS_BRANCH = master
|
|
||||||
#PROJECT_USER_FILE_EXTENSION = .user
|
|
||||||
|
|
||||||
set(IDE_VERSION "4.10.82" CACHE STRING "The IDE version.")
|
|
||||||
set(IDE_VERSION_COMPAT "4.10.82" CACHE STRING "The IDE Compatibility version.")
|
|
||||||
set(IDE_VERSION_DISPLAY "4.11.0-beta1" CACHE STRING "The IDE display version.")
|
|
||||||
set(IDE_COPYRIGHT_YEAR "2019" CACHE STRING "The IDE copyright year.")
|
|
||||||
|
|
||||||
set(IDE_REVISION FALSE CACHE BOOL "Marks the presence of IDE revision string.")
|
|
||||||
set(IDE_REVISION_STR "" CACHE STRING "The IDE revision string.")
|
|
||||||
set(IDE_SETTINGSVARIANT "QtProject" CACHE STRING "The IDE settings variation.")
|
|
||||||
set(IDE_COPY_SETTINGSVARIANT "Nokia" CACHE STRING "The IDE settings to initially import.")
|
|
||||||
set(IDE_DISPLAY_NAME "Qt Creator" CACHE STRING "The IDE display name.")
|
|
||||||
set(IDE_ID "qtcreator" CACHE STRING "The IDE id (no spaces, lowercase!)")
|
|
||||||
set(IDE_CASED_ID "QtCreator" CACHE STRING "The cased IDE id (no spaces!)")
|
|
||||||
set(IDE_BUNDLE_IDENTIFIER "org.qt-project.${IDE_ID}" CACHE STRING "The macOS application bundle identifier.")
|
|
||||||
|
|
||||||
mark_as_advanced(IDE_VERSION_COMPAT IDE_VERSION_DISPLAY IDE_COPYRIGHT_YEAR
|
|
||||||
IDE_REVISION IDE_REVISION_STR IDE_SETTINGSVARIANT IDE_COPY_SETTINGSVARIANT
|
|
||||||
IDE_DISPLAY_NAME IDE_ID IDE_CASED_ID IDE_BUNDLE_IDENTIFIER)
|
|
||||||
|
|
||||||
project(QtCreator VERSION ${IDE_VERSION})
|
|
||||||
|
|
||||||
## Add paths to check for cmake modules:
|
## Add paths to check for cmake modules:
|
||||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
||||||
|
|
||||||
|
include(FeatureSummary)
|
||||||
|
include(QtCreatorIDEBranding)
|
||||||
|
|
||||||
|
set(IDE_REVISION FALSE CACHE BOOL "Marks the presence of IDE revision string.")
|
||||||
|
set(IDE_REVISION_STR "" CACHE STRING "The IDE revision string.")
|
||||||
|
|
||||||
|
mark_as_advanced(IDE_REVISION IDE_REVISION_STR)
|
||||||
|
|
||||||
|
project(QtCreator VERSION ${IDE_VERSION})
|
||||||
|
|
||||||
# Force C++ standard, do not fall back, do not use compiler extensions
|
# Force C++ standard, do not fall back, do not use compiler extensions
|
||||||
set(CMAKE_CXX_STANDARD 14)
|
set(CMAKE_CXX_STANDARD 14)
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
@@ -127,7 +112,7 @@ endif()
|
|||||||
set(_IDE_APP_PATH "bin")
|
set(_IDE_APP_PATH "bin")
|
||||||
|
|
||||||
if (APPLE)
|
if (APPLE)
|
||||||
set(_IDE_APP_TARGET "Qt Creator")
|
set(_IDE_APP_TARGET "${IDE_DISPLAY_NAME}")
|
||||||
|
|
||||||
set(_IDE_OUTPUT_PATH "${_IDE_APP_PATH}/${_IDE_APP_TARGET}.app/Contents")
|
set(_IDE_OUTPUT_PATH "${_IDE_APP_PATH}/${_IDE_APP_TARGET}.app/Contents")
|
||||||
|
|
||||||
@@ -139,7 +124,7 @@ if (APPLE)
|
|||||||
set(_IDE_DOC_PATH "${_IDE_OUTPUT_PATH}/Resources/doc")
|
set(_IDE_DOC_PATH "${_IDE_OUTPUT_PATH}/Resources/doc")
|
||||||
set(_IDE_BIN_PATH "${_IDE_OUTPUT_PATH}/MacOS")
|
set(_IDE_BIN_PATH "${_IDE_OUTPUT_PATH}/MacOS")
|
||||||
else ()
|
else ()
|
||||||
set(_IDE_APP_TARGET "qtcreator")
|
set(_IDE_APP_TARGET "${IDE_ID}")
|
||||||
|
|
||||||
set(_IDE_LIBRARY_BASE_PATH "lib")
|
set(_IDE_LIBRARY_BASE_PATH "lib")
|
||||||
set(_IDE_LIBRARY_PATH "lib/qtcreator")
|
set(_IDE_LIBRARY_PATH "lib/qtcreator")
|
||||||
@@ -154,15 +139,15 @@ else ()
|
|||||||
set(_IDE_BIN_PATH "bin")
|
set(_IDE_BIN_PATH "bin")
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
set(IDE_APP_PATH "${_IDE_APP_PATH}" CACHE PATH "The target path of the IDE application (relative to CMAKE_INSTALL_PREFIX).")
|
set(IDE_APP_PATH "${_IDE_APP_PATH}") # The target path of the IDE application (relative to CMAKE_INSTALL_PREFIX).
|
||||||
set(IDE_APP_TARGET "${_IDE_APP_TARGET}" CACHE PATH "The IDE application name.")
|
set(IDE_APP_TARGET "${_IDE_APP_TARGET}") # The IDE application name.
|
||||||
set(IDE_PLUGIN_PATH "${_IDE_PLUGIN_PATH}" CACHE PATH "The IDE plugin path (relative to CMAKE_INSTALL_PREFIX).")
|
set(IDE_PLUGIN_PATH "${_IDE_PLUGIN_PATH}") # The IDE plugin path (relative to CMAKE_INSTALL_PREFIX).
|
||||||
set(IDE_LIBRARY_BASE_PATH "${_IDE_LIBRARY_BASE_PATH}" CACHE PATH "The IDE library base path (relative to CMAKE_INSTALL_PREFIX).")
|
set(IDE_LIBRARY_BASE_PATH "${_IDE_LIBRARY_BASE_PATH}") # The IDE library base path (relative to CMAKE_INSTALL_PREFIX).
|
||||||
set(IDE_LIBRARY_PATH "${_IDE_LIBRARY_PATH}" CACHE PATH "The IDE library path (relative to CMAKE_INSTALL_PREFIX).")
|
set(IDE_LIBRARY_PATH "${_IDE_LIBRARY_PATH}") # The IDE library path (relative to CMAKE_INSTALL_PREFIX).
|
||||||
set(IDE_LIBEXEC_PATH "${_IDE_LIBEXEC_PATH}" CACHE PATH "The IDE libexec path (relative to CMAKE_INSTALL_PREFIX).")
|
set(IDE_LIBEXEC_PATH "${_IDE_LIBEXEC_PATH}") # The IDE libexec path (relative to CMAKE_INSTALL_PREFIX).
|
||||||
set(IDE_DATA_PATH "${_IDE_DATA_PATH}" CACHE PATH "The IDE data path (relative to CMAKE_INSTALL_PREFIX).")
|
set(IDE_DATA_PATH "${_IDE_DATA_PATH}") # The IDE data path (relative to CMAKE_INSTALL_PREFIX).
|
||||||
set(IDE_DOC_PATH "${_IDE_DOC_PATH}" CACHE PATH "The IDE documentation path (relative to CMAKE_INSTALL_PREFIX).")
|
set(IDE_DOC_PATH "${_IDE_DOC_PATH}") # The IDE documentation path (relative to CMAKE_INSTALL_PREFIX).
|
||||||
set(IDE_BIN_PATH "${_IDE_BIN_PATH}" CACHE PATH "The IDE bin path (relative to CMAKE_INSTALL_PREFIX).")
|
set(IDE_BIN_PATH "${_IDE_BIN_PATH}") # The IDE bin path (relative to CMAKE_INSTALL_PREFIX).
|
||||||
|
|
||||||
file(RELATIVE_PATH RELATIVE_PLUGIN_PATH "/${IDE_BIN_PATH}" "/${IDE_PLUGIN_PATH}")
|
file(RELATIVE_PATH RELATIVE_PLUGIN_PATH "/${IDE_BIN_PATH}" "/${IDE_PLUGIN_PATH}")
|
||||||
file(RELATIVE_PATH RELATIVE_LIBEXEC_PATH "/${IDE_BIN_PATH}" "/${IDE_LIBEXEC_PATH}")
|
file(RELATIVE_PATH RELATIVE_LIBEXEC_PATH "/${IDE_BIN_PATH}" "/${IDE_LIBEXEC_PATH}")
|
||||||
|
14
cmake/QtCreatorIDEBranding.cmake
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
#BINARY_ARTIFACTS_BRANCH = master
|
||||||
|
#PROJECT_USER_FILE_EXTENSION = .user
|
||||||
|
|
||||||
|
set(IDE_VERSION "4.9.83") # The IDE version.
|
||||||
|
set(IDE_VERSION_COMPAT "4.9.83") # The IDE Compatibility version.
|
||||||
|
set(IDE_VERSION_DISPLAY "4.10.0-beta2") # The IDE display version.
|
||||||
|
set(IDE_COPYRIGHT_YEAR "2019") # The IDE copyright year.
|
||||||
|
|
||||||
|
set(IDE_SETTINGSVARIANT "QtProject") # The IDE settings variation.
|
||||||
|
set(IDE_COPY_SETTINGSVARIANT "Nokia") # The IDE settings to initially import.
|
||||||
|
set(IDE_DISPLAY_NAME "Qt Creator") # The IDE display name.
|
||||||
|
set(IDE_ID "qtcreator") # The IDE id (no spaces, lowercase!)
|
||||||
|
set(IDE_CASED_ID "QtCreator") # The cased IDE id (no spaces!)
|
||||||
|
set(IDE_BUNDLE_IDENTIFIER "org.qt-project.${IDE_ID}") # The macOS application bundle identifier.
|
20
dist/changes-4.10.0.md
vendored
@@ -13,6 +13,12 @@ you can check out from the public Git repository. For example:
|
|||||||
|
|
||||||
* Removed support for KDE code paster after removal of official API
|
* Removed support for KDE code paster after removal of official API
|
||||||
* Added option for pinning files so they stay open when closing all files (QTCREATORBUG-21899)
|
* Added option for pinning files so they stay open when closing all files (QTCREATORBUG-21899)
|
||||||
|
* Fixed low contrast of hovered folding markers (QTCREATORBUG-21702)
|
||||||
|
|
||||||
|
### Generic Highlighter
|
||||||
|
|
||||||
|
* Fixed that highlighting definition with MIME type `text/plain`
|
||||||
|
overrode better matching definitions (QTCREATORBUG-22540)
|
||||||
|
|
||||||
### Language Client
|
### Language Client
|
||||||
|
|
||||||
@@ -96,6 +102,9 @@ you can check out from the public Git repository. For example:
|
|||||||
|
|
||||||
* Improved auto-insertion of closing curly brace (QTCREATORBUG-18872)
|
* Improved auto-insertion of closing curly brace (QTCREATORBUG-18872)
|
||||||
* Fixed that snippet completion could get in the way (QTCREATORBUG-21767)
|
* Fixed that snippet completion could get in the way (QTCREATORBUG-21767)
|
||||||
|
* Fixed crash because of small stack size (QTCREATORBUG-22496)
|
||||||
|
* Fixed recognition of C++ version (QTCREATORBUG-22444)
|
||||||
|
* Fixed `unknown argument: '-fno-keep-inline-dllexport'` (QTCREATORBUG-22452)
|
||||||
|
|
||||||
### Clang Format
|
### Clang Format
|
||||||
|
|
||||||
@@ -105,6 +114,8 @@ you can check out from the public Git repository. For example:
|
|||||||
## QML Support
|
## QML Support
|
||||||
|
|
||||||
* Fixed various formatting issues
|
* Fixed various formatting issues
|
||||||
|
* Fixed incorrect syntax warning in JavaScript template literal
|
||||||
|
(QTCREATORBUG-22474)
|
||||||
|
|
||||||
## Debugging
|
## Debugging
|
||||||
|
|
||||||
@@ -127,6 +138,7 @@ you can check out from the public Git repository. For example:
|
|||||||
* Added gradient picker that allows loading and saving of presets
|
* Added gradient picker that allows loading and saving of presets
|
||||||
* Added support for changing properties for multiple items at once (QDS-324)
|
* Added support for changing properties for multiple items at once (QDS-324)
|
||||||
* Added missing properties for `LineEdit` and `ComboBox`
|
* Added missing properties for `LineEdit` and `ComboBox`
|
||||||
|
* Added all fonts from project directory to font selector (QDS-100)
|
||||||
* Updated properties of `Flickable`
|
* Updated properties of `Flickable`
|
||||||
* Improved handling of errors in state editor (QDS-695)
|
* Improved handling of errors in state editor (QDS-695)
|
||||||
|
|
||||||
@@ -154,13 +166,12 @@ you can check out from the public Git repository. For example:
|
|||||||
* Added `Clone` for MSVC toolchains (QTCREATORBUG-22163)
|
* Added `Clone` for MSVC toolchains (QTCREATORBUG-22163)
|
||||||
* Fixed that `mingw32-make`'s warnings were categorized as errors (QTCREATORBUG-22171)
|
* Fixed that `mingw32-make`'s warnings were categorized as errors (QTCREATORBUG-22171)
|
||||||
* Fixed bitness detection for MinGW (QTCREATORBUG-22160)
|
* Fixed bitness detection for MinGW (QTCREATORBUG-22160)
|
||||||
|
* Fixed registration as post mortem debugger on recent Windows versions
|
||||||
|
|
||||||
### Linux
|
### Linux
|
||||||
|
|
||||||
* Improved auto-detection of toolchains (QTCREATORBUG-19179, QTCREATORBUG-20044, QTCREATORBUG-22081)
|
* Improved auto-detection of toolchains (QTCREATORBUG-19179, QTCREATORBUG-20044, QTCREATORBUG-22081)
|
||||||
|
|
||||||
### macOS
|
|
||||||
|
|
||||||
### Android
|
### Android
|
||||||
|
|
||||||
* Removed support for MIPS64
|
* Removed support for MIPS64
|
||||||
@@ -172,13 +183,12 @@ you can check out from the public Git repository. For example:
|
|||||||
* Added support for opening remote terminal with run environment
|
* Added support for opening remote terminal with run environment
|
||||||
* Added option for `rsync` flags for deployment (QTCREATORBUG-22352)
|
* Added option for `rsync` flags for deployment (QTCREATORBUG-22352)
|
||||||
|
|
||||||
### Boot to Qt
|
|
||||||
|
|
||||||
### Bare Metal
|
### Bare Metal
|
||||||
|
|
||||||
* Added include path detection and output parsers for `IAR`, `KEIL` and `SDCC` toolchains
|
* Added include path detection and output parsers for `IAR`, `KEIL` and `SDCC` toolchains
|
||||||
|
|
||||||
## Credits for these changes go to:
|
## Credits for these changes go to:
|
||||||
|
|
||||||
Aleksei German
|
Aleksei German
|
||||||
Alessandro Ambrosano
|
Alessandro Ambrosano
|
||||||
Alessandro Portale
|
Alessandro Portale
|
||||||
@@ -208,10 +218,12 @@ Ivan Komissarov
|
|||||||
Joel Smith
|
Joel Smith
|
||||||
Jörg Bornemann
|
Jörg Bornemann
|
||||||
Kavindra Palaraja
|
Kavindra Palaraja
|
||||||
|
Knud Dollereder
|
||||||
Leena Miettinen
|
Leena Miettinen
|
||||||
Luca Carlon
|
Luca Carlon
|
||||||
Marco Bubke
|
Marco Bubke
|
||||||
Martin Haase
|
Martin Haase
|
||||||
|
Michael Weghorn
|
||||||
Mitch Curtis
|
Mitch Curtis
|
||||||
Nikolai Kosjar
|
Nikolai Kosjar
|
||||||
Oliver Wolff
|
Oliver Wolff
|
||||||
|
56
dist/changes-4.9.2.md
vendored
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
# Qt Creator 4.9.2
|
||||||
|
|
||||||
|
Qt Creator version 4.9.2 contains bug fixes.
|
||||||
|
|
||||||
|
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/v4.9.1..v4.9.2
|
||||||
|
|
||||||
|
## General
|
||||||
|
|
||||||
|
* Fixed display of shortcuts in `Keyboard` preferences (QTCREATORBUG-22333)
|
||||||
|
|
||||||
|
## Editing
|
||||||
|
|
||||||
|
* Fixed disabled editor close button in Design mode (QTCREATORBUG-22553)
|
||||||
|
|
||||||
|
### Syntax Highlighting
|
||||||
|
|
||||||
|
* Fixed highlighting issue while editing (QTCREATORBUG-22290)
|
||||||
|
|
||||||
|
## All Projects
|
||||||
|
|
||||||
|
* Fixed saving state of `Hide Empty Directories`
|
||||||
|
* Fixed crash that could happen after project parsing failed
|
||||||
|
|
||||||
|
## C++ Support
|
||||||
|
|
||||||
|
* Fixed expansion of `%DATE%` in license templates (QTCREATORBUG-22440)
|
||||||
|
|
||||||
|
## Qt Quick Designer
|
||||||
|
|
||||||
|
* Fixed crash on malformed QML (QDS-778)
|
||||||
|
|
||||||
|
## Platform Specific
|
||||||
|
|
||||||
|
### macOS
|
||||||
|
|
||||||
|
* Re-enabled graphics card switching that was disabled as a workaround
|
||||||
|
for OpenGL issues on macOS 10.14.4 (QTCREATORBUG-22215)
|
||||||
|
|
||||||
|
## Credits for these changes go to:
|
||||||
|
|
||||||
|
Christian Kandeler
|
||||||
|
Christian Stenger
|
||||||
|
David Schulz
|
||||||
|
Eike Ziller
|
||||||
|
Leena Miettinen
|
||||||
|
Michl Voznesensky
|
||||||
|
Robert Löhning
|
||||||
|
Thomas Hartmann
|
||||||
|
Tim Jenssen
|
||||||
|
Tobias Hunger
|
||||||
|
Ulf Hermann
|
BIN
doc/images/qtcreator-autotests-options-boost.png
Normal file
After Width: | Height: | Size: 5.5 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 7.1 KiB |
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 7.3 KiB |
Before Width: | Height: | Size: 7.0 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 43 KiB |
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 8.6 KiB |
@@ -1,6 +1,6 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
**
|
**
|
||||||
** Copyright (C) 2018 The Qt Company Ltd.
|
** Copyright (C) 2019 The Qt Company Ltd.
|
||||||
** Contact: https://www.qt.io/licensing/
|
** Contact: https://www.qt.io/licensing/
|
||||||
**
|
**
|
||||||
** This file is part of the Qt Creator documentation.
|
** This file is part of the Qt Creator documentation.
|
||||||
@@ -43,6 +43,9 @@
|
|||||||
native build configurations and workspaces that you can use in the compiler
|
native build configurations and workspaces that you can use in the compiler
|
||||||
environment of your choice.
|
environment of your choice.
|
||||||
|
|
||||||
|
You can use CMake from \QC to build applications for the desktop and
|
||||||
|
Android devices. You can also build single files to test your changes.
|
||||||
|
|
||||||
\QC automatically detects the CMake executable specified in the \c PATH.
|
\QC automatically detects the CMake executable specified in the \c PATH.
|
||||||
You can add paths to other CMake executables and use them in different
|
You can add paths to other CMake executables and use them in different
|
||||||
build and run \l{glossary-buildandrun-kit}{kits}.
|
build and run \l{glossary-buildandrun-kit}{kits}.
|
||||||
@@ -109,6 +112,8 @@
|
|||||||
|
|
||||||
\li Code completion
|
\li Code completion
|
||||||
|
|
||||||
|
\li Path completion
|
||||||
|
|
||||||
\li Auto-indentation
|
\li Auto-indentation
|
||||||
|
|
||||||
\li Matching parentheses and quotes
|
\li Matching parentheses and quotes
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
**
|
**
|
||||||
** Copyright (C) 2018 The Qt Company Ltd.
|
** Copyright (C) 2019 The Qt Company Ltd.
|
||||||
** Contact: https://www.qt.io/licensing/
|
** Contact: https://www.qt.io/licensing/
|
||||||
**
|
**
|
||||||
** This file is part of the Qt Creator documentation.
|
** This file is part of the Qt Creator documentation.
|
||||||
@@ -31,27 +31,28 @@
|
|||||||
|
|
||||||
\title Running Autotests
|
\title Running Autotests
|
||||||
|
|
||||||
\QC integrates the \l{Qt Test} framework and
|
\QC integrates the \l{Qt Test} framework,
|
||||||
\l{https://github.com/google/googletest}{Google C++ Testing Framework} for
|
\l{https://github.com/google/googletest}{Google C++ Testing Framework}, and
|
||||||
unit testing applications and libraries. You can use \QC to build and run
|
\l{https://www.boost.org/doc/libs/1_70_0/libs/test/doc/html/index.html}
|
||||||
Qt tests, Qt Quick tests (QML-based Qt tests), and Google tests for your
|
{Boost.Test} for unit testing applications and libraries. You can use \QC to
|
||||||
projects.
|
create, build, and run Qt tests, Qt Quick tests (QML-based Qt tests), Google
|
||||||
|
tests, and Boost tests for your projects.
|
||||||
|
|
||||||
\image qtcreator-autotests.png
|
\image qtcreator-autotests.png
|
||||||
|
|
||||||
\section1 Creating Tests
|
\section1 Creating Tests
|
||||||
|
|
||||||
You can use a wizard to create projects that contain Qt or Google tests.
|
You can use a wizard to create projects that contain tests.
|
||||||
|
|
||||||
\section2 Creating Qt Tests
|
\section2 Creating Qt and Qt Quick Tests
|
||||||
|
|
||||||
To create a Qt test:
|
To create a Qt or Qt Quick test:
|
||||||
|
|
||||||
\list 1
|
\list 1
|
||||||
\li Select \uicontrol File > \uicontrol {New File or Project} >
|
\li Select \uicontrol File > \uicontrol {New File or Project} >
|
||||||
\uicontrol {Other Project} > \uicontrol {Auto Test Project} >
|
\uicontrol {Other Project} > \uicontrol {Auto Test Project} >
|
||||||
\uicontrol Choose to create a project with boilerplate code for a
|
\uicontrol Choose to create a project with boilerplate code for a
|
||||||
Qt test.
|
Qt test or a Qt Quick test.
|
||||||
|
|
||||||
\li In the \uicontrol {Project and Test Information} dialog, specify
|
\li In the \uicontrol {Project and Test Information} dialog, specify
|
||||||
settings for the project and test:
|
settings for the project and test:
|
||||||
@@ -59,17 +60,17 @@
|
|||||||
\list 1
|
\list 1
|
||||||
|
|
||||||
\li In the \uicontrol {Test framework} field, select
|
\li In the \uicontrol {Test framework} field, select
|
||||||
\uicontrol {Qt Test}.
|
\uicontrol {Qt Test} or \uicontrol {Qt Quick Test}.
|
||||||
|
|
||||||
\li Select the \uicontrol {GUI Application} check box to create
|
\li For a Qt test, select the \uicontrol {GUI Application} check
|
||||||
a Qt application.
|
box to create a Qt application.
|
||||||
|
|
||||||
\li In the \uicontrol {Test case name} field, enter a name for
|
\li In the \uicontrol {Test case name} field, enter a name for
|
||||||
the test case.
|
the test case.
|
||||||
|
|
||||||
\li Select the \uicontrol {Requires QApplication} check box to
|
\li For a Qt test, select the \uicontrol {Requires \QApplication}
|
||||||
add the include statement for QApplication to the main.cpp
|
check box to add the include statement for QApplication to
|
||||||
file of the project.
|
the main.cpp file of the project.
|
||||||
|
|
||||||
\li Select the \uicontrol {Generate initialization and cleanup
|
\li Select the \uicontrol {Generate initialization and cleanup
|
||||||
code} checkbox to add functions to your test that are
|
code} checkbox to add functions to your test that are
|
||||||
@@ -135,6 +136,46 @@
|
|||||||
\l{https://github.com/google/googletest/blob/master/googletest/docs/primer.md}
|
\l{https://github.com/google/googletest/blob/master/googletest/docs/primer.md}
|
||||||
{Google Test Primer}.
|
{Google Test Primer}.
|
||||||
|
|
||||||
|
\section2 Creating Boost Tests
|
||||||
|
|
||||||
|
To build and run Boost tests, you must have the Boost.Test installed on the
|
||||||
|
development host. Typically, it is installed when you install Boost. You can
|
||||||
|
download Boost from \l{https://www.boost.org/}{Boost.org}.
|
||||||
|
|
||||||
|
If Boost libraries can be found by the used compiler and build system, you
|
||||||
|
do not need to specify the include directory when creating the test.
|
||||||
|
|
||||||
|
To create a Boost test:
|
||||||
|
|
||||||
|
\list 1
|
||||||
|
\li Select \uicontrol File > \uicontrol {New File or Project} >
|
||||||
|
\uicontrol {Other Project} > \uicontrol {Auto Test Project} >
|
||||||
|
\uicontrol Choose to create a project with boilerplate code for a
|
||||||
|
Boost test.
|
||||||
|
\li In the \uicontrol {Project and Test Information} dialog, specify
|
||||||
|
settings for the project and test:
|
||||||
|
\list 1
|
||||||
|
\li In the \uicontrol {Test framework} field, select
|
||||||
|
\uicontrol {Boost Test}.
|
||||||
|
\li In the \uicontrol {Test suite name} field, enter a name for
|
||||||
|
the test suite.
|
||||||
|
\li In the \uicontrol {Test case name} field, enter a name for
|
||||||
|
the test case.
|
||||||
|
\li In the \uicontrol {Boost include dir (optional)} field,
|
||||||
|
enter the path to the directory that contains files needed
|
||||||
|
by Boost.Test, such as \e version.hpp and a subfolder called
|
||||||
|
\e test that contains the test header files.
|
||||||
|
\li In the \uicontrol {Build system} field, select the build
|
||||||
|
system to use for building the project: qmake, CMake, or
|
||||||
|
Qbs.
|
||||||
|
\endlist
|
||||||
|
\endlist
|
||||||
|
|
||||||
|
\QC creates the test in the specified project directory.
|
||||||
|
For more information about creating Boost tests, see
|
||||||
|
\l{https://www.boost.org/doc/libs/1_70_0/libs/test/doc/html/index.html}
|
||||||
|
{Boost.Test}.
|
||||||
|
|
||||||
\section1 Setting Up the Google C++ Testing Framework
|
\section1 Setting Up the Google C++ Testing Framework
|
||||||
|
|
||||||
To build and run Google tests, you must have the Google C++ Testing
|
To build and run Google tests, you must have the Google C++ Testing
|
||||||
@@ -310,6 +351,30 @@
|
|||||||
failures into C++ exceptions, select the \uicontrol {Throw on failure} check
|
failures into C++ exceptions, select the \uicontrol {Throw on failure} check
|
||||||
box.
|
box.
|
||||||
|
|
||||||
|
\section2 Specifying Settings for Running Boost Tests
|
||||||
|
|
||||||
|
\list 1
|
||||||
|
\li To specify settings for running Boost tests, select \uicontrol Tools
|
||||||
|
> \uicontrol Options > \uicontrol {Testing} >
|
||||||
|
\uicontrol {Boost Test}.
|
||||||
|
\image qtcreator-autotests-options-boost.png
|
||||||
|
\li In the \uicontrol {Log format} field, select the error report
|
||||||
|
format to specify the type of events you want recorded in the
|
||||||
|
test report.
|
||||||
|
\li In the \uicontrol {Report level} field, select the verbosity level
|
||||||
|
of the test result report. Select \uicontrol No if you do not want
|
||||||
|
a report.
|
||||||
|
\li Select the \uicontrol Randomize check box to execute the tests in
|
||||||
|
a random order, using the seed specified in the \uicontrol Seed
|
||||||
|
field for initializing the randomizer.
|
||||||
|
\li Select the \uicontrol {Catch system errors} check box to catch
|
||||||
|
system errors.
|
||||||
|
\li Select the \uicontrol {Floating point exceptions} check box to
|
||||||
|
detect floating point exceptions.
|
||||||
|
\li Select the \uicontrol {Detect memory leaks} check box to detect
|
||||||
|
memory leaks.
|
||||||
|
\endlist
|
||||||
|
|
||||||
\section1 Viewing Test Output
|
\section1 Viewing Test Output
|
||||||
|
|
||||||
The test results are displayed in the \uicontrol {Test Results} output pane
|
The test results are displayed in the \uicontrol {Test Results} output pane
|
||||||
|
@@ -116,9 +116,9 @@
|
|||||||
execution. In addition, the QML Profiler enables you to profile
|
execution. In addition, the QML Profiler enables you to profile
|
||||||
Qt Quick applications.
|
Qt Quick applications.
|
||||||
|
|
||||||
\QC is integrated to the \l{Qt Test} and Google C++ Testing
|
\QC is integrated to the \l{Qt Test}, Google C++ Testing, and
|
||||||
frameworks for unit testing applications and libraries. You can
|
Boost.Test frameworks for unit testing applications and
|
||||||
use \QC to build and run autotests.
|
libraries. You can use \QC to create, build, and run autotests.
|
||||||
|
|
||||||
For more information, see \l{Testing}.
|
For more information, see \l{Testing}.
|
||||||
\li \b {Publishing}
|
\li \b {Publishing}
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
**
|
**
|
||||||
** Copyright (C) 2018 The Qt Company Ltd.
|
** Copyright (C) 2019 The Qt Company Ltd.
|
||||||
** Contact: https://www.qt.io/licensing/
|
** Contact: https://www.qt.io/licensing/
|
||||||
**
|
**
|
||||||
** This file is part of the Qt Creator documentation.
|
** This file is part of the Qt Creator documentation.
|
||||||
@@ -60,9 +60,8 @@
|
|||||||
|
|
||||||
\li \l{Running Autotests}
|
\li \l{Running Autotests}
|
||||||
|
|
||||||
You can build and run Qt tests, Qt Quick tests, and Google tests
|
You can create, build and run Qt tests, Qt Quick tests, Google
|
||||||
using \QC. In addition, you can use a wizard to create projects that
|
tests, and Boost tests using \QC.
|
||||||
contain Qt or Google tests.
|
|
||||||
|
|
||||||
\endlist
|
\endlist
|
||||||
|
|
||||||
|
@@ -153,7 +153,7 @@ class PlainDumper:
|
|||||||
if d.isExpanded():
|
if d.isExpanded():
|
||||||
with Children(d):
|
with Children(d):
|
||||||
for child in children:
|
for child in children:
|
||||||
d.putSubItem(child[0], d.fromNativeValue(child[1]))
|
d.putSubItem(child[0], d.fromNativeValue(gdb.Value(child[1])))
|
||||||
|
|
||||||
def importPlainDumpers(args):
|
def importPlainDumpers(args):
|
||||||
if args == 'off':
|
if args == 'off':
|
||||||
|
@@ -953,34 +953,18 @@ def qdumpHelper__std__vector(d, value, isLibCpp):
|
|||||||
innerType = value.type[0]
|
innerType = value.type[0]
|
||||||
isBool = innerType.name == 'bool'
|
isBool = innerType.name == 'bool'
|
||||||
|
|
||||||
try:
|
|
||||||
allocator = value.type[1].name
|
|
||||||
except:
|
|
||||||
allocator = ''
|
|
||||||
|
|
||||||
isStdAllocator = allocator == 'std::allocator<%s>' % innerType.name
|
|
||||||
|
|
||||||
if isBool:
|
if isBool:
|
||||||
if isLibCpp:
|
if isLibCpp:
|
||||||
if isStdAllocator:
|
|
||||||
(start, size) = value.split("pp") # start is 'unsigned long *'
|
|
||||||
else:
|
|
||||||
start = value["__begin_"].pointer()
|
start = value["__begin_"].pointer()
|
||||||
size = value["__size_"]
|
size = value["__size_"]
|
||||||
alloc = size
|
alloc = size
|
||||||
else:
|
|
||||||
if isStdAllocator:
|
|
||||||
(start, soffset, pad, finish, foffset, pad, alloc) = value.split("pI@pI@p")
|
|
||||||
else:
|
else:
|
||||||
start = value["_M_start"]["_M_p"].pointer()
|
start = value["_M_start"]["_M_p"].pointer()
|
||||||
soffset = value["_M_start"]["_M_offset"]
|
soffset = value["_M_start"]["_M_offset"].integer()
|
||||||
finish = value["_M_finish"]["_M_p"].pointer()
|
finish = value["_M_finish"]["_M_p"].pointer()
|
||||||
foffset = value["_M_finish"]["_M_offset"]
|
foffset = value["_M_finish"]["_M_offset"].integer()
|
||||||
alloc = value["_M_end_of_storage"].pointer()
|
alloc = value["_M_end_of_storage"].pointer()
|
||||||
size = (finish - start) * 8 + foffset - soffset # 8 is CHAR_BIT.
|
size = (finish - start) * 8 + foffset - soffset # 8 is CHAR_BIT.
|
||||||
else:
|
|
||||||
if isStdAllocator:
|
|
||||||
(start, finish, alloc) = value.split("ppp")
|
|
||||||
else:
|
else:
|
||||||
if isLibCpp:
|
if isLibCpp:
|
||||||
start = value["__begin_"].pointer()
|
start = value["__begin_"].pointer()
|
||||||
@@ -1088,14 +1072,7 @@ def qdump__std__basic_string(d, value):
|
|||||||
def qdump__std____cxx11__basic_string(d, value):
|
def qdump__std____cxx11__basic_string(d, value):
|
||||||
innerType = value.type[0]
|
innerType = value.type[0]
|
||||||
try:
|
try:
|
||||||
allocator = value.type[2].name
|
data = value["_M_dataplus"]["_M_p"].pointer()
|
||||||
except:
|
|
||||||
allocator = ''
|
|
||||||
if allocator == 'std::allocator<%s>' % innerType.name:
|
|
||||||
(data, size) = value.split("pI")
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
data = value["_M_dataplus"]["_M_p"]
|
|
||||||
size = int(value["_M_string_length"])
|
size = int(value["_M_string_length"])
|
||||||
except:
|
except:
|
||||||
d.putEmptyValue()
|
d.putEmptyValue()
|
||||||
|
@@ -39,7 +39,35 @@ StudioControls.ComboBox {
|
|||||||
onTextColorChanged: setColor()
|
onTextColorChanged: setColor()
|
||||||
|
|
||||||
editable: true
|
editable: true
|
||||||
model: ["Arial", "Times New Roman", "Courier", "Verdana", "Tahoma"]
|
|
||||||
|
property string fontFilter: "*.ttf *.otf"
|
||||||
|
|
||||||
|
|
||||||
|
FileResourcesModel {
|
||||||
|
modelNodeBackendProperty: modelNodeBackend
|
||||||
|
filter: comboBox.fontFilter
|
||||||
|
id: fileModel
|
||||||
|
}
|
||||||
|
|
||||||
|
function fontUrlToName(url) {
|
||||||
|
var fontLoader = Qt.createQmlObject('import QtQuick 2.0; FontLoader { source: \"' + url + '\"; }',
|
||||||
|
comboBox,
|
||||||
|
"dynamicFontLoader");
|
||||||
|
return fontLoader.name
|
||||||
|
}
|
||||||
|
|
||||||
|
function setupModel() {
|
||||||
|
var files = fileModel.fileModel
|
||||||
|
var familyNames = ["Arial", "Times New Roman", "Courier", "Verdana", "Tahoma"]
|
||||||
|
|
||||||
|
files.forEach(function (item, index) {
|
||||||
|
var name = fontUrlToName(fileModel.dirPath + "/" + item)
|
||||||
|
familyNames.push(name)
|
||||||
|
});
|
||||||
|
|
||||||
|
familyNames.sort()
|
||||||
|
comboBox.model = familyNames
|
||||||
|
}
|
||||||
|
|
||||||
onModelChanged: {
|
onModelChanged: {
|
||||||
editText = comboBox.backendValue.valueToString
|
editText = comboBox.backendValue.valueToString
|
||||||
@@ -97,10 +125,12 @@ StudioControls.ComboBox {
|
|||||||
target: modelNodeBackend
|
target: modelNodeBackend
|
||||||
onSelectionChanged: {
|
onSelectionChanged: {
|
||||||
comboBox.editText = backendValue.value
|
comboBox.editText = backendValue.value
|
||||||
|
setupModel()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
|
setupModel()
|
||||||
//Hack to style the text input
|
//Hack to style the text input
|
||||||
for (var i = 0; i < comboBox.children.length; i++) {
|
for (var i = 0; i < comboBox.children.length; i++) {
|
||||||
if (comboBox.children[i].text !== undefined) {
|
if (comboBox.children[i].text !== undefined) {
|
||||||
|
@@ -9,7 +9,7 @@
|
|||||||
"iconText": "java",
|
"iconText": "java",
|
||||||
"enabled": "%{JS: value('Plugins').indexOf('Android') >= 0}",
|
"enabled": "%{JS: value('Plugins').indexOf('Android') >= 0}",
|
||||||
|
|
||||||
"options": [ { "key": "ClassName", "value": "%{JS: value('FileName').charAt(0).toUpperCase() + value('FileName').substr(1).replace(/\\.java$/,'')}" } ],
|
"options": [ { "key": "ClassName", "value": "%{JS: value('FileName').charAt(0).toUpperCase() + value('FileName').substr(1).replace(/[.]java$/,'')}" } ],
|
||||||
|
|
||||||
"pages" :
|
"pages" :
|
||||||
[
|
[
|
||||||
|
@@ -2,7 +2,7 @@ import qbs
|
|||||||
|
|
||||||
Application {
|
Application {
|
||||||
@if "%{UseVirtualKeyboard}" == "true"
|
@if "%{UseVirtualKeyboard}" == "true"
|
||||||
Depends { name: "Qt"; submodules: "quick", "virtualkeyboard" }
|
Depends { name: "Qt"; submodules: ["quick", "virtualkeyboard"] }
|
||||||
@else
|
@else
|
||||||
Depends { name: "Qt.quick" }
|
Depends { name: "Qt.quick" }
|
||||||
@endif
|
@endif
|
||||||
|
@@ -14,7 +14,7 @@
|
|||||||
{ "key": "vcsId", "value": "B.Bazaar" },
|
{ "key": "vcsId", "value": "B.Bazaar" },
|
||||||
{ "key": "vcsName", "value": "%{JS: Vcs.displayName('%{vcsId}')}" },
|
{ "key": "vcsName", "value": "%{JS: Vcs.displayName('%{vcsId}')}" },
|
||||||
{ "key": "SR", "value": "%{JS: '%{Repo}'.substr('%{Repo}'.indexOf(':') + 1) }" },
|
{ "key": "SR", "value": "%{JS: '%{Repo}'.substr('%{Repo}'.indexOf(':') + 1) }" },
|
||||||
{ "key": "defaultDir", "value": "%{JS: '%{SR}'.substr('%{SR}'.lastIndexOf('/') + 1).replace(/\\./, '-') }"},
|
{ "key": "defaultDir", "value": "%{JS: '%{SR}'.substr('%{SR}'.lastIndexOf('/') + 1).replace(/[.]/g, '-') }"},
|
||||||
{ "key": "RevArg", "value": "%{JS: '%{Rev}' !== '' ? '-r' : ''}" },
|
{ "key": "RevArg", "value": "%{JS: '%{Rev}' !== '' ? '-r' : ''}" },
|
||||||
{ "key": "TargetPath", "value": "%{Path}/%{Dir}" }
|
{ "key": "TargetPath", "value": "%{Path}/%{Dir}" }
|
||||||
],
|
],
|
||||||
|
@@ -13,8 +13,8 @@
|
|||||||
[
|
[
|
||||||
{ "key": "vcsId", "value": "G.Git" },
|
{ "key": "vcsId", "value": "G.Git" },
|
||||||
{ "key": "vcsName", "value": "%{JS: Vcs.displayName('%{vcsId}')}" },
|
{ "key": "vcsName", "value": "%{JS: Vcs.displayName('%{vcsId}')}" },
|
||||||
{ "key": "SR", "value": "%{JS: '%{Repo}'.replace(/\\.git$/, '') }"},
|
{ "key": "SR", "value": "%{JS: '%{Repo}'.replace(/[.]git$/, '') }"},
|
||||||
{ "key": "defaultDir", "value": "%{JS: '%{SR}'.substr('%{SR}'.lastIndexOf('/') + 1).replace(/\\./, '-') }"},
|
{ "key": "defaultDir", "value": "%{JS: '%{SR}'.substr('%{SR}'.lastIndexOf('/') + 1).replace(/[.]/g, '-') }"},
|
||||||
{ "key": "branchArg", "value": "%{JS: '%{Branch}' ? '--branch' : '' }" },
|
{ "key": "branchArg", "value": "%{JS: '%{Branch}' ? '--branch' : '' }" },
|
||||||
{ "key": "TargetPath", "value": "%{Path}/%{Dir}" }
|
{ "key": "TargetPath", "value": "%{Path}/%{Dir}" }
|
||||||
],
|
],
|
||||||
|
@@ -14,7 +14,7 @@
|
|||||||
{ "key": "vcsId", "value": "H.Mercurial" },
|
{ "key": "vcsId", "value": "H.Mercurial" },
|
||||||
{ "key": "vcsName", "value": "%{JS: Vcs.displayName('%{vcsId}')}" },
|
{ "key": "vcsName", "value": "%{JS: Vcs.displayName('%{vcsId}')}" },
|
||||||
{ "key": "SR", "value": "%{JS: '%{Repo}'.substr('%{Repo}'.indexOf(':') + 1) }"},
|
{ "key": "SR", "value": "%{JS: '%{Repo}'.substr('%{Repo}'.indexOf(':') + 1) }"},
|
||||||
{ "key": "defaultDir", "value": "%{JS: '%{SR}'.substr('%{SR}'.lastIndexOf('/') + 1).replace(/\\./, '-') }"},
|
{ "key": "defaultDir", "value": "%{JS: '%{SR}'.substr('%{SR}'.lastIndexOf('/') + 1).replace(/[.]/g, '-') }"},
|
||||||
{ "key": "TargetPath", "value": "%{Path}/%{Dir}" }
|
{ "key": "TargetPath", "value": "%{Path}/%{Dir}" }
|
||||||
],
|
],
|
||||||
|
|
||||||
|
@@ -13,8 +13,8 @@
|
|||||||
[
|
[
|
||||||
{ "key": "vcsId", "value": "J.Subversion" },
|
{ "key": "vcsId", "value": "J.Subversion" },
|
||||||
{ "key": "vcsName", "value": "%{JS: Vcs.displayName('%{vcsId}')}" },
|
{ "key": "vcsName", "value": "%{JS: Vcs.displayName('%{vcsId}')}" },
|
||||||
{ "key": "SR", "value": "%{JS: '%{Repo}'.replace(/\\/trunk$/, '').replace(/\\/$/, '') }"},
|
{ "key": "SR", "value": "%{JS: '%{Repo}'.replace(/[/]trunk$/, '').replace(/[/]$/, '') }"},
|
||||||
{ "key": "defaultDir", "value": "%{JS: '%{SR}'.substr('%{SR}'.lastIndexOf('/') + 1).replace(/\\./, '-') }"},
|
{ "key": "defaultDir", "value": "%{JS: '%{SR}'.substr('%{SR}'.lastIndexOf('/') + 1).replace(/[.]/g, '-') }"},
|
||||||
{ "key": "TargetPath", "value": "%{Path}/%{Dir}" }
|
{ "key": "TargetPath", "value": "%{Path}/%{Dir}" }
|
||||||
],
|
],
|
||||||
|
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<!DOCTYPE TS>
|
<!DOCTYPE TS>
|
||||||
<TS version="2.0" language="fr">
|
<TS version="2.1" language="fr">
|
||||||
<context>
|
<context>
|
||||||
<name>Application</name>
|
<name>Application</name>
|
||||||
<message>
|
<message>
|
||||||
@@ -42412,7 +42412,7 @@ au gestionnaire de version (%2)</translation>
|
|||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Set Message Tracepoint at Line %1...</source>
|
<source>Set Message Tracepoint at Line %1...</source>
|
||||||
<translation>Définir un message de traçace à la ligne %1...</translation>
|
<translation>Définir un message de traçage à la ligne %1...</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Disassemble Function "%1"</source>
|
<source>Disassemble Function "%1"</source>
|
||||||
@@ -70891,7 +70891,7 @@ réinitialisation du moniteur</translation>
|
|||||||
<message>
|
<message>
|
||||||
<source>Get Started Now</source>
|
<source>Get Started Now</source>
|
||||||
<translatorcomment>attention à la longueur du texte, doit reste petit</translatorcomment>
|
<translatorcomment>attention à la longueur du texte, doit reste petit</translatorcomment>
|
||||||
<translation type="unfinished">Démarrer</translation>
|
<translation>Démarrer</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Online Community</source>
|
<source>Online Community</source>
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
/****************************************************************************
|
; /****************************************************************************
|
||||||
**
|
**
|
||||||
** Copyright (C) 2016 The Qt Company Ltd.
|
** Copyright (C) 2016 The Qt Company Ltd.
|
||||||
** Contact: https://www.qt.io/licensing/
|
** Contact: https://www.qt.io/licensing/
|
||||||
@@ -27,71 +27,94 @@
|
|||||||
|
|
||||||
#include "clangpathwatcherinterface.h"
|
#include "clangpathwatcherinterface.h"
|
||||||
#include "clangpathwatchernotifier.h"
|
#include "clangpathwatchernotifier.h"
|
||||||
#include "changedfilepathcompressor.h"
|
#include "directorypathcompressor.h"
|
||||||
#include "filepathcachinginterface.h"
|
#include "filepathcachinginterface.h"
|
||||||
|
#include "filesystem.h"
|
||||||
#include "stringcache.h"
|
#include "stringcache.h"
|
||||||
|
|
||||||
|
#include <utils/algorithm.h>
|
||||||
|
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
|
||||||
namespace ClangBackEnd {
|
namespace ClangBackEnd {
|
||||||
|
|
||||||
|
template<class InputIt1, class InputIt2, class Callable>
|
||||||
|
void set_greedy_intersection_call(
|
||||||
|
InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2, Callable callable)
|
||||||
|
{
|
||||||
|
while (first1 != last1 && first2 != last2) {
|
||||||
|
if (*first1 < *first2) {
|
||||||
|
++first1;
|
||||||
|
} else {
|
||||||
|
if (*first2 < *first1)
|
||||||
|
++first2;
|
||||||
|
else
|
||||||
|
callable(*first1++);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class WatcherEntry
|
class WatcherEntry
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ProjectPartId id;
|
ProjectPartId id;
|
||||||
FilePathId pathId;
|
DirectoryPathId directoryPathId;
|
||||||
|
FilePathId filePathId;
|
||||||
|
long long lastModified = -1;
|
||||||
|
|
||||||
friend bool operator==(WatcherEntry first, WatcherEntry second)
|
friend bool operator==(WatcherEntry first, WatcherEntry second)
|
||||||
{
|
{
|
||||||
return first.id == second.id && first.pathId == second.pathId;
|
return first.id == second.id && first.directoryPathId == second.directoryPathId
|
||||||
|
&& first.filePathId == second.filePathId;
|
||||||
}
|
}
|
||||||
|
|
||||||
friend bool operator<(WatcherEntry first, WatcherEntry second)
|
friend bool operator<(WatcherEntry first, WatcherEntry second)
|
||||||
{
|
{
|
||||||
return std::tie(first.pathId, first.id) < std::tie(second.pathId, second.id);
|
return std::tie(first.directoryPathId, first.filePathId, first.id)
|
||||||
|
< std::tie(second.directoryPathId, second.filePathId, second.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
friend bool operator<(WatcherEntry entry, FilePathId pathId)
|
friend bool operator<(DirectoryPathId directoryPathId, WatcherEntry entry)
|
||||||
{
|
{
|
||||||
return entry.pathId < pathId;
|
return directoryPathId < entry.directoryPathId;
|
||||||
}
|
}
|
||||||
|
|
||||||
friend bool operator<(FilePathId pathId, WatcherEntry entry)
|
friend bool operator<(WatcherEntry entry, DirectoryPathId directoryPathId)
|
||||||
{
|
{
|
||||||
return pathId < entry.pathId;
|
return entry.directoryPathId < directoryPathId;
|
||||||
}
|
}
|
||||||
|
|
||||||
operator FilePathId() const
|
operator FilePathId() const { return filePathId; }
|
||||||
{
|
|
||||||
return pathId;
|
operator DirectoryPathId() const { return directoryPathId; }
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
using WatcherEntries = std::vector<WatcherEntry>;
|
using WatcherEntries = std::vector<WatcherEntry>;
|
||||||
|
|
||||||
template <typename FileSystemWatcher,
|
template<typename FileSystemWatcher, typename Timer>
|
||||||
typename Timer>
|
|
||||||
class CLANGSUPPORT_GCCEXPORT ClangPathWatcher : public ClangPathWatcherInterface
|
class CLANGSUPPORT_GCCEXPORT ClangPathWatcher : public ClangPathWatcherInterface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ClangPathWatcher(FilePathCachingInterface &pathCache,
|
ClangPathWatcher(FilePathCachingInterface &pathCache,
|
||||||
ClangPathWatcherNotifier *notifier=nullptr)
|
FileSystemInterface &fileSystem,
|
||||||
: m_changedFilePathCompressor(pathCache),
|
ClangPathWatcherNotifier *notifier = nullptr)
|
||||||
m_pathCache(pathCache),
|
: m_pathCache(pathCache)
|
||||||
m_notifier(notifier)
|
, m_fileStatusCache(fileSystem)
|
||||||
|
, m_fileSystem(fileSystem)
|
||||||
|
, m_notifier(notifier)
|
||||||
{
|
{
|
||||||
QObject::connect(&m_fileSystemWatcher,
|
QObject::connect(&m_fileSystemWatcher,
|
||||||
&FileSystemWatcher::fileChanged,
|
&FileSystemWatcher::directoryChanged,
|
||||||
[&] (const QString &filePath) { compressChangedFilePath(filePath); });
|
[&](const QString &path) { compressChangedDirectoryPath(path); });
|
||||||
|
|
||||||
m_changedFilePathCompressor.setCallback([&] (ClangBackEnd::FilePathIds &&filePathIds) {
|
m_directoryPathCompressor.setCallback([&](ClangBackEnd::DirectoryPathIds &&directoryPathIds) {
|
||||||
addChangedPathForFilePath(std::move(filePathIds));
|
addChangedPathForFilePath(std::move(directoryPathIds));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
~ClangPathWatcher()
|
~ClangPathWatcher()
|
||||||
{
|
{
|
||||||
m_changedFilePathCompressor.setCallback([&] (FilePathIds &&) {});
|
m_directoryPathCompressor.setCallback([&](DirectoryPathIds &&) {});
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateIdPaths(const std::vector<IdPaths> &idPaths) override
|
void updateIdPaths(const std::vector<IdPaths> &idPaths) override
|
||||||
@@ -109,7 +132,7 @@ public:
|
|||||||
auto filteredPaths = filterNotWatchedPaths(removedEntries);
|
auto filteredPaths = filterNotWatchedPaths(removedEntries);
|
||||||
|
|
||||||
if (!filteredPaths.empty())
|
if (!filteredPaths.empty())
|
||||||
m_fileSystemWatcher.removePaths(convertWatcherEntriesToQStringList(filteredPaths));
|
m_fileSystemWatcher.removePaths(convertWatcherEntriesToDirectoryPathList(filteredPaths));
|
||||||
}
|
}
|
||||||
|
|
||||||
void setNotifier(ClangPathWatcherNotifier *notifier) override
|
void setNotifier(ClangPathWatcherNotifier *notifier) override
|
||||||
@@ -164,7 +187,13 @@ public:
|
|||||||
outputIterator = std::transform(idPath.filePathIds.begin(),
|
outputIterator = std::transform(idPath.filePathIds.begin(),
|
||||||
idPath.filePathIds.end(),
|
idPath.filePathIds.end(),
|
||||||
outputIterator,
|
outputIterator,
|
||||||
[&] (FilePathId pathId) { return WatcherEntry{id, pathId}; });
|
[&](FilePathId filePathId) {
|
||||||
|
return WatcherEntry{
|
||||||
|
id,
|
||||||
|
m_pathCache.directoryPathId(filePathId),
|
||||||
|
filePathId,
|
||||||
|
m_fileStatusCache.lastModifiedTime(filePathId)};
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
std::sort(entries.begin(), entries.end());
|
std::sort(entries.begin(), entries.end());
|
||||||
@@ -182,7 +211,7 @@ public:
|
|||||||
mergeToWatchedEntries(newEntries);
|
mergeToWatchedEntries(newEntries);
|
||||||
|
|
||||||
if (!filteredPaths.empty())
|
if (!filteredPaths.empty())
|
||||||
m_fileSystemWatcher.addPaths(convertWatcherEntriesToQStringList(filteredPaths));
|
m_fileSystemWatcher.addPaths(convertWatcherEntriesToDirectoryPathList(filteredPaths));
|
||||||
}
|
}
|
||||||
|
|
||||||
void removeUnusedEntries(const WatcherEntries &entries, const ProjectPartIds &ids)
|
void removeUnusedEntries(const WatcherEntries &entries, const ProjectPartIds &ids)
|
||||||
@@ -194,33 +223,31 @@ public:
|
|||||||
auto filteredPaths = filterNotWatchedPaths(oldEntries);
|
auto filteredPaths = filterNotWatchedPaths(oldEntries);
|
||||||
|
|
||||||
if (!filteredPaths.empty())
|
if (!filteredPaths.empty())
|
||||||
m_fileSystemWatcher.removePaths(convertWatcherEntriesToQStringList(filteredPaths));
|
m_fileSystemWatcher.removePaths(convertWatcherEntriesToDirectoryPathList(filteredPaths));
|
||||||
}
|
}
|
||||||
|
|
||||||
FileSystemWatcher &fileSystemWatcher()
|
FileSystemWatcher &fileSystemWatcher() { return m_fileSystemWatcher; }
|
||||||
{
|
|
||||||
return m_fileSystemWatcher;
|
|
||||||
}
|
|
||||||
|
|
||||||
QStringList convertWatcherEntriesToQStringList(
|
QStringList convertWatcherEntriesToDirectoryPathList(const DirectoryPathIds &directoryPathIds) const
|
||||||
const WatcherEntries &watcherEntries)
|
|
||||||
{
|
{
|
||||||
QStringList paths;
|
return Utils::transform<QStringList>(directoryPathIds, [&](DirectoryPathId id) {
|
||||||
paths.reserve(int(watcherEntries.size()));
|
return QString(m_pathCache.directoryPath(id));
|
||||||
|
|
||||||
std::transform(watcherEntries.begin(),
|
|
||||||
watcherEntries.end(),
|
|
||||||
std::back_inserter(paths),
|
|
||||||
[&] (WatcherEntry entry) {
|
|
||||||
return QString(m_pathCache.filePath(entry.pathId).path());
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return paths;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Compare>
|
QStringList convertWatcherEntriesToDirectoryPathList(const WatcherEntries &watcherEntries) const
|
||||||
WatcherEntries notWatchedEntries(const WatcherEntries &entries,
|
{
|
||||||
Compare compare) const
|
DirectoryPathIds directoryPathIds = Utils::transform<DirectoryPathIds>(
|
||||||
|
watcherEntries, [&](WatcherEntry entry) { return entry.directoryPathId; });
|
||||||
|
|
||||||
|
std::sort(directoryPathIds.begin(), directoryPathIds.end());
|
||||||
|
directoryPathIds.erase(std::unique(directoryPathIds.begin(), directoryPathIds.end()),
|
||||||
|
directoryPathIds.end());
|
||||||
|
|
||||||
|
return convertWatcherEntriesToDirectoryPathList(directoryPathIds);
|
||||||
|
}
|
||||||
|
|
||||||
|
WatcherEntries notWatchedEntries(const WatcherEntries &entries) const
|
||||||
{
|
{
|
||||||
WatcherEntries notWatchedEntries;
|
WatcherEntries notWatchedEntries;
|
||||||
notWatchedEntries.reserve(entries.size());
|
notWatchedEntries.reserve(entries.size());
|
||||||
@@ -229,24 +256,23 @@ public:
|
|||||||
entries.end(),
|
entries.end(),
|
||||||
m_watchedEntries.cbegin(),
|
m_watchedEntries.cbegin(),
|
||||||
m_watchedEntries.cend(),
|
m_watchedEntries.cend(),
|
||||||
std::back_inserter(notWatchedEntries),
|
std::back_inserter(notWatchedEntries));
|
||||||
compare);
|
|
||||||
|
|
||||||
return notWatchedEntries;
|
return notWatchedEntries;
|
||||||
}
|
}
|
||||||
|
|
||||||
WatcherEntries notWatchedEntries(const WatcherEntries &entries) const
|
DirectoryPathIds notWatchedPaths(const DirectoryPathIds &ids) const
|
||||||
{
|
{
|
||||||
return notWatchedEntries(entries, std::less<WatcherEntry>());
|
DirectoryPathIds notWatchedDirectoryIds;
|
||||||
}
|
notWatchedDirectoryIds.reserve(ids.size());
|
||||||
|
|
||||||
WatcherEntries notWatchedPaths(const WatcherEntries &entries) const
|
std::set_difference(ids.begin(),
|
||||||
{
|
ids.end(),
|
||||||
auto compare = [] (WatcherEntry first, WatcherEntry second) {
|
m_watchedEntries.cbegin(),
|
||||||
return first.pathId < second.pathId;
|
m_watchedEntries.cend(),
|
||||||
};
|
std::back_inserter(notWatchedDirectoryIds));
|
||||||
|
|
||||||
return notWatchedEntries(entries, compare);
|
return notWatchedDirectoryIds;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Compare>
|
template <typename Compare>
|
||||||
@@ -297,25 +323,24 @@ public:
|
|||||||
m_watchedEntries = std::move(newWatchedEntries);
|
m_watchedEntries = std::move(newWatchedEntries);
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static DirectoryPathIds uniquePaths(const WatcherEntries &pathEntries)
|
||||||
WatcherEntries uniquePaths(const WatcherEntries &pathEntries)
|
|
||||||
{
|
{
|
||||||
WatcherEntries uniqueEntries;
|
DirectoryPathIds uniqueDirectoryIds;
|
||||||
uniqueEntries.reserve(pathEntries.size());
|
uniqueDirectoryIds.reserve(pathEntries.size());
|
||||||
|
|
||||||
auto compare = [] (WatcherEntry first, WatcherEntry second) {
|
auto compare = [](WatcherEntry first, WatcherEntry second) {
|
||||||
return first.pathId == second.pathId;
|
return first.directoryPathId == second.directoryPathId;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::unique_copy(pathEntries.begin(),
|
std::unique_copy(pathEntries.begin(),
|
||||||
pathEntries.end(),
|
pathEntries.end(),
|
||||||
std::back_inserter(uniqueEntries),
|
std::back_inserter(uniqueDirectoryIds),
|
||||||
compare);
|
compare);
|
||||||
|
|
||||||
return uniqueEntries;
|
return uniqueDirectoryIds;
|
||||||
}
|
}
|
||||||
|
|
||||||
WatcherEntries filterNotWatchedPaths(const WatcherEntries &entries)
|
DirectoryPathIds filterNotWatchedPaths(const WatcherEntries &entries) const
|
||||||
{
|
{
|
||||||
return notWatchedPaths(uniquePaths(entries));
|
return notWatchedPaths(uniquePaths(entries));
|
||||||
}
|
}
|
||||||
@@ -351,40 +376,48 @@ public:
|
|||||||
oldEntries.end(),
|
oldEntries.end(),
|
||||||
std::back_inserter(newWatchedEntries));
|
std::back_inserter(newWatchedEntries));
|
||||||
|
|
||||||
|
m_watchedEntries = std::move(newWatchedEntries);
|
||||||
m_watchedEntries = newWatchedEntries;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void compressChangedFilePath(const QString &filePath)
|
void compressChangedDirectoryPath(const QString &path)
|
||||||
{
|
{
|
||||||
m_changedFilePathCompressor.addFilePath(filePath);
|
m_directoryPathCompressor.addDirectoryPathId(
|
||||||
|
m_pathCache.directoryPathId(Utils::PathString{path}));
|
||||||
}
|
}
|
||||||
|
|
||||||
WatcherEntries watchedEntriesForPaths(ClangBackEnd::FilePathIds &&filePathIds)
|
WatcherEntries watchedEntriesForPaths(ClangBackEnd::DirectoryPathIds &&directoryPathIds)
|
||||||
{
|
{
|
||||||
WatcherEntries foundEntries;
|
WatcherEntries foundEntries;
|
||||||
foundEntries.reserve(filePathIds.size());
|
foundEntries.reserve(m_watchedEntries.size());
|
||||||
|
|
||||||
for (FilePathId pathId : filePathIds) {
|
set_greedy_intersection_call(m_watchedEntries.begin(),
|
||||||
auto range = std::equal_range(m_watchedEntries.begin(), m_watchedEntries.end(), pathId);
|
m_watchedEntries.end(),
|
||||||
foundEntries.insert(foundEntries.end(), range.first, range.second);
|
directoryPathIds.begin(),
|
||||||
|
directoryPathIds.end(),
|
||||||
|
[&](WatcherEntry &entry) {
|
||||||
|
m_fileStatusCache.update(entry.filePathId);
|
||||||
|
auto currentLastModified = m_fileStatusCache.lastModifiedTime(
|
||||||
|
entry.filePathId);
|
||||||
|
if (entry.lastModified < currentLastModified) {
|
||||||
|
foundEntries.push_back(entry);
|
||||||
|
entry.lastModified = currentLastModified;
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
return foundEntries;
|
return foundEntries;
|
||||||
}
|
}
|
||||||
|
|
||||||
FilePathIds watchedPaths(const FilePathIds &filePathIds) const
|
FilePathIds watchedPaths(const WatcherEntries &entries) const
|
||||||
{
|
{
|
||||||
FilePathIds watchedFilePathIds;
|
auto filePathIds = Utils::transform<FilePathIds>(entries, [](WatcherEntry entry) {
|
||||||
watchedFilePathIds.reserve(filePathIds.size());
|
return entry.filePathId;
|
||||||
|
});
|
||||||
|
|
||||||
std::set_intersection(m_watchedEntries.begin(),
|
std::sort(filePathIds.begin(), filePathIds.end());
|
||||||
m_watchedEntries.end(),
|
|
||||||
filePathIds.begin(),
|
|
||||||
filePathIds.end(),
|
|
||||||
std::back_inserter(watchedFilePathIds));
|
|
||||||
|
|
||||||
return watchedFilePathIds;
|
filePathIds.erase(std::unique(filePathIds.begin(), filePathIds.end()), filePathIds.end());
|
||||||
|
|
||||||
|
return filePathIds;
|
||||||
}
|
}
|
||||||
|
|
||||||
ProjectPartIds idsForWatcherEntries(const WatcherEntries &foundEntries)
|
ProjectPartIds idsForWatcherEntries(const WatcherEntries &foundEntries)
|
||||||
@@ -403,21 +436,20 @@ public:
|
|||||||
ProjectPartIds uniqueIds(ProjectPartIds &&ids)
|
ProjectPartIds uniqueIds(ProjectPartIds &&ids)
|
||||||
{
|
{
|
||||||
std::sort(ids.begin(), ids.end());
|
std::sort(ids.begin(), ids.end());
|
||||||
auto newEnd = std::unique(ids.begin(), ids.end());
|
ids.erase(std::unique(ids.begin(), ids.end()), ids.end());
|
||||||
ids.erase(newEnd, ids.end());
|
|
||||||
|
|
||||||
return std::move(ids);
|
return std::move(ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
void addChangedPathForFilePath(FilePathIds &&filePathIds)
|
void addChangedPathForFilePath(DirectoryPathIds &&directoryPathIds)
|
||||||
{
|
{
|
||||||
if (m_notifier) {
|
if (m_notifier) {
|
||||||
WatcherEntries foundEntries = watchedEntriesForPaths(std::move(filePathIds));
|
WatcherEntries foundEntries = watchedEntriesForPaths(std::move(directoryPathIds));
|
||||||
|
|
||||||
ProjectPartIds changedIds = idsForWatcherEntries(foundEntries);
|
ProjectPartIds changedIds = idsForWatcherEntries(foundEntries);
|
||||||
|
|
||||||
m_notifier->pathsWithIdsChanged(uniqueIds(std::move(changedIds)));
|
m_notifier->pathsWithIdsChanged(uniqueIds(std::move(changedIds)));
|
||||||
m_notifier->pathsChanged(watchedPaths(filePathIds));
|
m_notifier->pathsChanged(watchedPaths(foundEntries));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -428,10 +460,12 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
WatcherEntries m_watchedEntries;
|
WatcherEntries m_watchedEntries;
|
||||||
ChangedFilePathCompressor<Timer> m_changedFilePathCompressor;
|
|
||||||
FileSystemWatcher m_fileSystemWatcher;
|
FileSystemWatcher m_fileSystemWatcher;
|
||||||
|
FileStatusCache m_fileStatusCache;
|
||||||
|
FileSystemInterface &m_fileSystem;
|
||||||
FilePathCachingInterface &m_pathCache;
|
FilePathCachingInterface &m_pathCache;
|
||||||
ClangPathWatcherNotifier *m_notifier;
|
ClangPathWatcherNotifier *m_notifier;
|
||||||
|
DirectoryPathCompressor<Timer> m_directoryPathCompressor;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ClangBackEnd
|
} // namespace ClangBackEnd
|
||||||
|
@@ -18,6 +18,7 @@ SOURCES += \
|
|||||||
$$PWD/clangcodemodelserverproxy.cpp \
|
$$PWD/clangcodemodelserverproxy.cpp \
|
||||||
$$PWD/alivemessage.cpp \
|
$$PWD/alivemessage.cpp \
|
||||||
$$PWD/completionsmessage.cpp \
|
$$PWD/completionsmessage.cpp \
|
||||||
|
$$PWD/filesystem.cpp \
|
||||||
$$PWD/requestcompletionsmessage.cpp \
|
$$PWD/requestcompletionsmessage.cpp \
|
||||||
$$PWD/echomessage.cpp \
|
$$PWD/echomessage.cpp \
|
||||||
$$PWD/endmessage.cpp \
|
$$PWD/endmessage.cpp \
|
||||||
@@ -87,7 +88,8 @@ SOURCES += \
|
|||||||
$$PWD/removegeneratedfilesmessage.cpp \
|
$$PWD/removegeneratedfilesmessage.cpp \
|
||||||
$$PWD/generatedfiles.cpp \
|
$$PWD/generatedfiles.cpp \
|
||||||
$$PWD/projectpartartefact.cpp \
|
$$PWD/projectpartartefact.cpp \
|
||||||
$$PWD/projectpartcontainer.cpp
|
$$PWD/projectpartcontainer.cpp \
|
||||||
|
$$PWD/filestatuscache.cpp
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
$$PWD/cancelmessage.h \
|
$$PWD/cancelmessage.h \
|
||||||
@@ -109,7 +111,11 @@ HEADERS += \
|
|||||||
$$PWD/alivemessage.h \
|
$$PWD/alivemessage.h \
|
||||||
$$PWD/clangsupportexceptions.h \
|
$$PWD/clangsupportexceptions.h \
|
||||||
$$PWD/completionsmessage.h \
|
$$PWD/completionsmessage.h \
|
||||||
|
$$PWD/directoryandfilepathid.h \
|
||||||
|
$$PWD/directorypathid.h \
|
||||||
$$PWD/executeinloop.h \
|
$$PWD/executeinloop.h \
|
||||||
|
$$PWD/filesystem.h \
|
||||||
|
$$PWD/filesysteminterface.h \
|
||||||
$$PWD/pchpaths.h \
|
$$PWD/pchpaths.h \
|
||||||
$$PWD/projectpartid.h \
|
$$PWD/projectpartid.h \
|
||||||
$$PWD/projectpartsstorage.h \
|
$$PWD/projectpartsstorage.h \
|
||||||
@@ -151,6 +157,7 @@ HEADERS += \
|
|||||||
$$PWD/refactoringserverinterface.h \
|
$$PWD/refactoringserverinterface.h \
|
||||||
$$PWD/refactoringserverproxy.h \
|
$$PWD/refactoringserverproxy.h \
|
||||||
$$PWD/referencesmessage.h \
|
$$PWD/referencesmessage.h \
|
||||||
|
$$PWD/set_algorithm.h \
|
||||||
$$PWD/unsavedfilesupdatedmessage.h \
|
$$PWD/unsavedfilesupdatedmessage.h \
|
||||||
$$PWD/removeprojectpartsmessage.h \
|
$$PWD/removeprojectpartsmessage.h \
|
||||||
$$PWD/requestannotationsmessage.h \
|
$$PWD/requestannotationsmessage.h \
|
||||||
@@ -217,6 +224,8 @@ HEADERS += \
|
|||||||
$$PWD/sourceentry.h \
|
$$PWD/sourceentry.h \
|
||||||
$$PWD/modifiedtimecheckerinterface.h \
|
$$PWD/modifiedtimecheckerinterface.h \
|
||||||
$$PWD/environment.h \
|
$$PWD/environment.h \
|
||||||
|
$$PWD/filestatus.h \
|
||||||
|
$$PWD/filestatuscache.h \
|
||||||
$$PWD/modifiedtimechecker.h
|
$$PWD/modifiedtimechecker.h
|
||||||
|
|
||||||
contains(QT_CONFIG, reduce_exports):CONFIG += hide_symbols
|
contains(QT_CONFIG, reduce_exports):CONFIG += hide_symbols
|
||||||
|
90
src/libs/clangsupport/directoryandfilepathid.h
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2019 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "directorypathid.h"
|
||||||
|
#include "filepathid.h"
|
||||||
|
|
||||||
|
#include <QDataStream>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace ClangBackEnd {
|
||||||
|
class DirectoryAndFilePathId
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
constexpr DirectoryAndFilePathId() = default;
|
||||||
|
|
||||||
|
DirectoryAndFilePathId(const char *) = delete;
|
||||||
|
|
||||||
|
DirectoryAndFilePathId(int directoryPathId, int filePathId)
|
||||||
|
: directoryPathId(directoryPathId)
|
||||||
|
, filePathId(filePathId)
|
||||||
|
{}
|
||||||
|
|
||||||
|
bool isValid() const { return directoryPathId.isValid() && filePathId.isValid(); }
|
||||||
|
|
||||||
|
friend bool operator==(DirectoryAndFilePathId first, DirectoryAndFilePathId second)
|
||||||
|
{
|
||||||
|
return first.isValid() && first.directoryPathId == second.directoryPathId
|
||||||
|
&& first.filePathId == second.filePathId;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend bool operator!=(DirectoryAndFilePathId first, DirectoryAndFilePathId second)
|
||||||
|
{
|
||||||
|
return !(first == second);
|
||||||
|
}
|
||||||
|
|
||||||
|
friend bool operator<(DirectoryAndFilePathId first, DirectoryAndFilePathId second)
|
||||||
|
{
|
||||||
|
return std::tie(first.directoryPathId, first.filePathId)
|
||||||
|
< std::tie(second.directoryPathId, second.filePathId);
|
||||||
|
}
|
||||||
|
|
||||||
|
friend QDataStream &operator<<(QDataStream &out,
|
||||||
|
const DirectoryAndFilePathId &directoryAndFilePathId)
|
||||||
|
{
|
||||||
|
out << directoryAndFilePathId.directoryPathId;
|
||||||
|
out << directoryAndFilePathId.filePathId;
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend QDataStream &operator>>(QDataStream &in, DirectoryAndFilePathId &directoryAndFilePathId)
|
||||||
|
{
|
||||||
|
in >> directoryAndFilePathId.directoryPathId;
|
||||||
|
in >> directoryAndFilePathId.filePathId;
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
DirectoryPathId directoryPathId;
|
||||||
|
FilePathId filePathId;
|
||||||
|
};
|
||||||
|
|
||||||
|
using DirectoryAndFilePathIds = std::vector<DirectoryAndFilePathId>;
|
||||||
|
|
||||||
|
} // namespace ClangBackEnd
|
@@ -27,53 +27,44 @@
|
|||||||
|
|
||||||
#include "clangsupport_global.h"
|
#include "clangsupport_global.h"
|
||||||
|
|
||||||
#include <filepathid.h>
|
#include "filepathcachinginterface.h"
|
||||||
#include <filepathcache.h>
|
|
||||||
|
|
||||||
|
#include <QDir>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
|
||||||
#include <filepathcachinginterface.h>
|
#include <utils/algorithm.h>
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
namespace ClangBackEnd {
|
namespace ClangBackEnd {
|
||||||
|
|
||||||
template <typename Timer>
|
template<typename Timer>
|
||||||
class ChangedFilePathCompressor
|
class DirectoryPathCompressor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ChangedFilePathCompressor(FilePathCachingInterface &filePathCache)
|
DirectoryPathCompressor() { m_timer.setSingleShot(true); }
|
||||||
: m_filePathCache(filePathCache)
|
|
||||||
|
virtual ~DirectoryPathCompressor() = default;
|
||||||
|
|
||||||
|
void addDirectoryPathId(DirectoryPathId directoryPathIdId)
|
||||||
{
|
{
|
||||||
m_timer.setSingleShot(true);
|
auto found = std::lower_bound(m_directoryPathIds.begin(),
|
||||||
}
|
m_directoryPathIds.end(),
|
||||||
|
directoryPathIdId);
|
||||||
|
|
||||||
virtual ~ChangedFilePathCompressor()
|
if (found == m_directoryPathIds.end() || *found != directoryPathIdId)
|
||||||
{
|
m_directoryPathIds.insert(found, directoryPathIdId);
|
||||||
}
|
|
||||||
|
|
||||||
void addFilePath(const QString &filePath)
|
|
||||||
{
|
|
||||||
FilePathId filePathId = m_filePathCache.filePathId(FilePath(filePath));
|
|
||||||
|
|
||||||
auto found = std::lower_bound(m_filePaths.begin(), m_filePaths.end(), filePathId);
|
|
||||||
|
|
||||||
if (found == m_filePaths.end() || *found != filePathId)
|
|
||||||
m_filePaths.insert(found, filePathId);
|
|
||||||
|
|
||||||
restartTimer();
|
restartTimer();
|
||||||
}
|
}
|
||||||
|
|
||||||
FilePathIds takeFilePathIds()
|
DirectoryPathIds takeDirectoryPathIds() { return std::move(m_directoryPathIds); }
|
||||||
{
|
|
||||||
return std::move(m_filePaths);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void setCallback(std::function<void(ClangBackEnd::FilePathIds &&)> &&callback)
|
virtual void setCallback(std::function<void(ClangBackEnd::DirectoryPathIds &&)> &&callback)
|
||||||
{
|
{
|
||||||
QObject::connect(&m_timer,
|
QObject::connect(&m_timer, &Timer::timeout, [this, callback = std::move(callback)] {
|
||||||
&Timer::timeout,
|
callback(takeDirectoryPathIds());
|
||||||
[this, callback=std::move(callback)] { callback(takeFilePathIds()); });
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
unittest_public:
|
unittest_public:
|
||||||
@@ -88,9 +79,8 @@ unittest_public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FilePathIds m_filePaths;
|
DirectoryPathIds m_directoryPathIds;
|
||||||
Timer m_timer;
|
Timer m_timer;
|
||||||
FilePathCachingInterface &m_filePathCache;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ClangBackEnd
|
} // namespace ClangBackEnd
|
81
src/libs/clangsupport/directorypathid.h
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2019 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QDataStream>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace ClangBackEnd {
|
||||||
|
class DirectoryPathId
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
constexpr DirectoryPathId() = default;
|
||||||
|
|
||||||
|
DirectoryPathId(const char *) = delete;
|
||||||
|
|
||||||
|
DirectoryPathId(int directoryPathId)
|
||||||
|
: directoryPathId(directoryPathId)
|
||||||
|
{}
|
||||||
|
|
||||||
|
bool isValid() const { return directoryPathId >= 0; }
|
||||||
|
|
||||||
|
friend bool operator==(DirectoryPathId first, DirectoryPathId second)
|
||||||
|
{
|
||||||
|
return first.isValid() && first.directoryPathId == second.directoryPathId;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend bool operator!=(DirectoryPathId first, DirectoryPathId second)
|
||||||
|
{
|
||||||
|
return !(first == second);
|
||||||
|
}
|
||||||
|
|
||||||
|
friend bool operator<(DirectoryPathId first, DirectoryPathId second)
|
||||||
|
{
|
||||||
|
return first.directoryPathId < second.directoryPathId;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend QDataStream &operator<<(QDataStream &out, const DirectoryPathId &directoryPathId)
|
||||||
|
{
|
||||||
|
out << directoryPathId.directoryPathId;
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend QDataStream &operator>>(QDataStream &in, DirectoryPathId &directoryPathId)
|
||||||
|
{
|
||||||
|
in >> directoryPathId.directoryPathId;
|
||||||
|
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
int directoryPathId = -1;
|
||||||
|
};
|
||||||
|
|
||||||
|
using DirectoryPathIds = std::vector<DirectoryPathId>;
|
||||||
|
|
||||||
|
} // namespace ClangBackEnd
|
@@ -25,9 +25,10 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "directorypathid.h"
|
||||||
|
#include "filepath.h"
|
||||||
#include "filepathexceptions.h"
|
#include "filepathexceptions.h"
|
||||||
#include "filepathid.h"
|
#include "filepathid.h"
|
||||||
#include "filepath.h"
|
|
||||||
#include "filepathview.h"
|
#include "filepathview.h"
|
||||||
#include "stringcache.h"
|
#include "stringcache.h"
|
||||||
|
|
||||||
@@ -121,8 +122,8 @@ public:
|
|||||||
{
|
{
|
||||||
Utils::SmallStringView directoryPath = filePath.directory();
|
Utils::SmallStringView directoryPath = filePath.directory();
|
||||||
|
|
||||||
int directoryId = m_directoryPathCache.stringId(directoryPath,
|
int directoryId = m_directoryPathCache.stringId(
|
||||||
[&] (const Utils::SmallStringView) {
|
directoryPath, [&](const Utils::SmallStringView directoryPath) {
|
||||||
return m_filePathStorage.fetchDirectoryId(directoryPath);
|
return m_filePathStorage.fetchDirectoryId(directoryPath);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -136,6 +137,17 @@ public:
|
|||||||
return fileNameId;
|
return fileNameId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DirectoryPathId directoryPathId(Utils::SmallStringView directoryPath) const
|
||||||
|
{
|
||||||
|
Utils::SmallStringView path = directoryPath.back() == '/'
|
||||||
|
? directoryPath.mid(0, directoryPath.size() - 1)
|
||||||
|
: directoryPath;
|
||||||
|
|
||||||
|
return m_directoryPathCache.stringId(path, [&](const Utils::SmallStringView directoryPath) {
|
||||||
|
return m_filePathStorage.fetchDirectoryId(directoryPath);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
FilePath filePath(FilePathId filePathId) const
|
FilePath filePath(FilePathId filePathId) const
|
||||||
{
|
{
|
||||||
if (Q_UNLIKELY(!filePathId.isValid()))
|
if (Q_UNLIKELY(!filePathId.isValid()))
|
||||||
@@ -157,6 +169,32 @@ public:
|
|||||||
return FilePath{directoryPath, entry.fileName};
|
return FilePath{directoryPath, entry.fileName};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Utils::PathString directoryPath(DirectoryPathId directoryPathId) const
|
||||||
|
{
|
||||||
|
if (Q_UNLIKELY(!directoryPathId.isValid()))
|
||||||
|
throw NoDirectoryPathForInvalidDirectoryPathId();
|
||||||
|
|
||||||
|
auto fetchDirectoryPath = [&](int id) { return m_filePathStorage.fetchDirectoryPath(id); };
|
||||||
|
|
||||||
|
return m_directoryPathCache.string(directoryPathId.directoryPathId, fetchDirectoryPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
DirectoryPathId directoryPathId(FilePathId filePathId) const
|
||||||
|
{
|
||||||
|
if (Q_UNLIKELY(!filePathId.isValid()))
|
||||||
|
throw NoFilePathForInvalidFilePathId();
|
||||||
|
|
||||||
|
auto fetchSoureNameAndDirectoryId = [&](int id) {
|
||||||
|
auto entry = m_filePathStorage.fetchSourceNameAndDirectoryId(id);
|
||||||
|
return FileNameEntry{entry.sourceName, entry.directoryId};
|
||||||
|
};
|
||||||
|
|
||||||
|
FileNameEntry entry = m_fileNameCache.string(filePathId.filePathId,
|
||||||
|
fetchSoureNameAndDirectoryId);
|
||||||
|
|
||||||
|
return m_fileNameCache.string(filePathId.filePathId, fetchSoureNameAndDirectoryId).directoryId;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
mutable DirectoryPathCache m_directoryPathCache;
|
mutable DirectoryPathCache m_directoryPathCache;
|
||||||
mutable FileNameCache m_fileNameCache;
|
mutable FileNameCache m_fileNameCache;
|
||||||
|
@@ -37,4 +37,19 @@ FilePath FilePathCaching::filePath(FilePathId filePathId) const
|
|||||||
return m_cache.filePath(filePathId);
|
return m_cache.filePath(filePathId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DirectoryPathId FilePathCaching::directoryPathId(Utils::SmallStringView directoryPath) const
|
||||||
|
{
|
||||||
|
return m_cache.directoryPathId(directoryPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
Utils::PathString FilePathCaching::directoryPath(DirectoryPathId directoryPathId) const
|
||||||
|
{
|
||||||
|
return m_cache.directoryPath(directoryPathId);
|
||||||
|
}
|
||||||
|
|
||||||
|
DirectoryPathId FilePathCaching::directoryPathId(FilePathId filePathId) const
|
||||||
|
{
|
||||||
|
return m_cache.directoryPathId(filePathId);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ClangBackEnd
|
} // namespace ClangBackEnd
|
||||||
|
@@ -50,6 +50,9 @@ public:
|
|||||||
|
|
||||||
FilePathId filePathId(FilePathView filePath) const override;
|
FilePathId filePathId(FilePathView filePath) const override;
|
||||||
FilePath filePath(FilePathId filePathId) const override;
|
FilePath filePath(FilePathId filePathId) const override;
|
||||||
|
DirectoryPathId directoryPathId(Utils::SmallStringView directoryPath) const override;
|
||||||
|
Utils::PathString directoryPath(DirectoryPathId directoryPathId) const override;
|
||||||
|
DirectoryPathId directoryPathId(FilePathId filePathId) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Factory m_factory;
|
Factory m_factory;
|
||||||
|
@@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "directorypathid.h"
|
||||||
#include "filepath.h"
|
#include "filepath.h"
|
||||||
#include "filepathid.h"
|
#include "filepathid.h"
|
||||||
#include "filepathview.h"
|
#include "filepathview.h"
|
||||||
@@ -40,8 +41,11 @@ public:
|
|||||||
|
|
||||||
virtual FilePathId filePathId(FilePathView filePath) const = 0;
|
virtual FilePathId filePathId(FilePathView filePath) const = 0;
|
||||||
virtual FilePath filePath(FilePathId filePathId) const = 0;
|
virtual FilePath filePath(FilePathId filePathId) const = 0;
|
||||||
|
virtual DirectoryPathId directoryPathId(Utils::SmallStringView directoryPath) const = 0;
|
||||||
|
virtual DirectoryPathId directoryPathId(FilePathId filePathId) const = 0;
|
||||||
|
virtual Utils::PathString directoryPath(DirectoryPathId directoryPathId) const = 0;
|
||||||
|
|
||||||
template <typename Container>
|
template<typename Container>
|
||||||
FilePathIds filePathIds(Container &&filePaths) const
|
FilePathIds filePathIds(Container &&filePaths) const
|
||||||
{
|
{
|
||||||
FilePathIds filePathIds;
|
FilePathIds filePathIds;
|
||||||
|
@@ -38,6 +38,15 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class NoDirectoryPathForInvalidDirectoryPathId : std::exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
const char *what() const noexcept override
|
||||||
|
{
|
||||||
|
return "You cannot get a directory path for an invalid directory path id!";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class SourceNameIdDoesNotExists : std::exception
|
class SourceNameIdDoesNotExists : std::exception
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@@ -179,12 +179,32 @@ public:
|
|||||||
|
|
||||||
transaction.commit();
|
transaction.commit();
|
||||||
|
|
||||||
return optionalSourceName.value();
|
return *optionalSourceName;
|
||||||
} catch (const Sqlite::StatementIsBusy &) {
|
} catch (const Sqlite::StatementIsBusy &) {
|
||||||
return fetchSourceNameAndDirectoryId(sourceId);
|
return fetchSourceNameAndDirectoryId(sourceId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int fetchDirectoryId(int sourceId)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
Sqlite::DeferredTransaction transaction{m_statementFactory.database};
|
||||||
|
|
||||||
|
ReadStatement &statement = m_statementFactory.selectDirectoryIdFromSourcesBySourceId;
|
||||||
|
|
||||||
|
auto optionalDirectoryId = statement.template value<int>(sourceId);
|
||||||
|
|
||||||
|
if (!optionalDirectoryId)
|
||||||
|
throw SourceNameIdDoesNotExists();
|
||||||
|
|
||||||
|
transaction.commit();
|
||||||
|
|
||||||
|
return *optionalDirectoryId;
|
||||||
|
} catch (const Sqlite::StatementIsBusy &) {
|
||||||
|
return fetchDirectoryId(sourceId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<Sources::Source> fetchAllSources()
|
std::vector<Sources::Source> fetchAllSources()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
@@ -69,6 +69,8 @@ public:
|
|||||||
"SELECT sourceName, directoryId FROM sources WHERE sourceId = ?",
|
"SELECT sourceName, directoryId FROM sources WHERE sourceId = ?",
|
||||||
database
|
database
|
||||||
};
|
};
|
||||||
|
ReadStatement selectDirectoryIdFromSourcesBySourceId{
|
||||||
|
"SELECT directoryId FROM sources WHERE sourceId = ?", database};
|
||||||
WriteStatement insertIntoSources{
|
WriteStatement insertIntoSources{
|
||||||
"INSERT INTO sources(directoryId, sourceName) VALUES (?,?)",
|
"INSERT INTO sources(directoryId, sourceName) VALUES (?,?)",
|
||||||
database
|
database
|
||||||
|
137
src/libs/clangsupport/filestatuscache.cpp
Normal file
@@ -0,0 +1,137 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2017 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "filestatuscache.h"
|
||||||
|
#include "filesystem.h"
|
||||||
|
|
||||||
|
#include <set_algorithm.h>
|
||||||
|
|
||||||
|
#include <utils/algorithm.h>
|
||||||
|
|
||||||
|
#include <QDateTime>
|
||||||
|
#include <QFileInfo>
|
||||||
|
|
||||||
|
namespace ClangBackEnd {
|
||||||
|
|
||||||
|
long long FileStatusCache::lastModifiedTime(FilePathId filePathId) const
|
||||||
|
{
|
||||||
|
return findEntry(filePathId).lastModified;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileStatusCache::update(FilePathId filePathId)
|
||||||
|
{
|
||||||
|
auto found = std::lower_bound(m_cacheEntries.begin(),
|
||||||
|
m_cacheEntries.end(),
|
||||||
|
Internal::FileStatusCacheEntry{filePathId},
|
||||||
|
[] (const auto &first, const auto &second) {
|
||||||
|
return first.filePathId < second.filePathId;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (found != m_cacheEntries.end() && found->filePathId == filePathId)
|
||||||
|
found->lastModified = m_fileSystem.lastModified(filePathId);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileStatusCache::update(FilePathIds filePathIds)
|
||||||
|
{
|
||||||
|
std::set_intersection(m_cacheEntries.begin(),
|
||||||
|
m_cacheEntries.end(),
|
||||||
|
filePathIds.begin(),
|
||||||
|
filePathIds.end(),
|
||||||
|
make_iterator([&](auto &entry) {
|
||||||
|
entry.lastModified = m_fileSystem.lastModified(entry.filePathId);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
FilePathIds FileStatusCache::modified(FilePathIds filePathIds) const
|
||||||
|
{
|
||||||
|
FilePathIds modifiedFilePathIds;
|
||||||
|
modifiedFilePathIds.reserve(filePathIds.size());
|
||||||
|
|
||||||
|
std::set_intersection(m_cacheEntries.begin(),
|
||||||
|
m_cacheEntries.end(),
|
||||||
|
filePathIds.begin(),
|
||||||
|
filePathIds.end(),
|
||||||
|
make_iterator([&](auto &entry) {
|
||||||
|
auto newLastModified = m_fileSystem.lastModified(entry.filePathId);
|
||||||
|
if (newLastModified > entry.lastModified) {
|
||||||
|
modifiedFilePathIds.push_back(entry.filePathId);
|
||||||
|
entry.lastModified = newLastModified;
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
Internal::FileStatusCacheEntries newEntries;
|
||||||
|
newEntries.reserve(filePathIds.size());
|
||||||
|
|
||||||
|
std::set_difference(filePathIds.begin(),
|
||||||
|
filePathIds.end(),
|
||||||
|
m_cacheEntries.begin(),
|
||||||
|
m_cacheEntries.end(),
|
||||||
|
make_iterator([&](FilePathId newFilePathId) {
|
||||||
|
newEntries.emplace_back(newFilePathId,
|
||||||
|
m_fileSystem.lastModified(newFilePathId));
|
||||||
|
modifiedFilePathIds.push_back(newFilePathId);
|
||||||
|
}));
|
||||||
|
|
||||||
|
if (newEntries.size()) {
|
||||||
|
Internal::FileStatusCacheEntries mergedEntries;
|
||||||
|
mergedEntries.reserve(m_cacheEntries.size() + newEntries.size());
|
||||||
|
|
||||||
|
std::set_union(newEntries.begin(),
|
||||||
|
newEntries.end(),
|
||||||
|
m_cacheEntries.begin(),
|
||||||
|
m_cacheEntries.end(),
|
||||||
|
std::back_inserter(mergedEntries));
|
||||||
|
|
||||||
|
m_cacheEntries = std::move(mergedEntries);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::sort(modifiedFilePathIds.begin(), modifiedFilePathIds.end());
|
||||||
|
|
||||||
|
return modifiedFilePathIds;
|
||||||
|
}
|
||||||
|
|
||||||
|
FileStatusCache::size_type FileStatusCache::size() const
|
||||||
|
{
|
||||||
|
return m_cacheEntries.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
Internal::FileStatusCacheEntry FileStatusCache::findEntry(FilePathId filePathId) const
|
||||||
|
{
|
||||||
|
auto found = std::lower_bound(m_cacheEntries.begin(),
|
||||||
|
m_cacheEntries.end(),
|
||||||
|
Internal::FileStatusCacheEntry{filePathId},
|
||||||
|
[] (const auto &first, const auto &second) {
|
||||||
|
return first.filePathId < second.filePathId;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (found != m_cacheEntries.end() && found->filePathId == filePathId)
|
||||||
|
return *found;
|
||||||
|
|
||||||
|
auto inserted = m_cacheEntries.emplace(found, filePathId, m_fileSystem.lastModified(filePathId));
|
||||||
|
|
||||||
|
return *inserted;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace ClangBackEnd
|
@@ -31,6 +31,8 @@ QT_FORWARD_DECLARE_CLASS(QFileInfo)
|
|||||||
|
|
||||||
namespace ClangBackEnd {
|
namespace ClangBackEnd {
|
||||||
|
|
||||||
|
class FileSystemInterface;
|
||||||
|
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
class FileStatusCacheEntry
|
class FileStatusCacheEntry
|
||||||
{
|
{
|
||||||
@@ -41,8 +43,23 @@ public:
|
|||||||
lastModified(lastModified)
|
lastModified(lastModified)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
friend bool operator<(FileStatusCacheEntry first, FileStatusCacheEntry second)
|
||||||
|
{
|
||||||
|
return first.filePathId < second.filePathId;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend bool operator<(FileStatusCacheEntry first, FilePathId second)
|
||||||
|
{
|
||||||
|
return first.filePathId < second;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend bool operator<(FilePathId first, FileStatusCacheEntry second)
|
||||||
|
{
|
||||||
|
return first < second.filePathId;
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ClangBackEnd::FilePathId filePathId;
|
FilePathId filePathId;
|
||||||
long long lastModified;
|
long long lastModified;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -50,27 +67,30 @@ using FileStatusCacheEntries = std::vector<FileStatusCacheEntry>;
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class FileStatusCache
|
class CLANGSUPPORT_EXPORT FileStatusCache
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using size_type = Internal::FileStatusCacheEntries::size_type;
|
using size_type = Internal::FileStatusCacheEntries::size_type;
|
||||||
|
|
||||||
FileStatusCache(FilePathCachingInterface &filePathCache);
|
FileStatusCache(FileSystemInterface &fileSystem)
|
||||||
|
: m_fileSystem(fileSystem)
|
||||||
|
{}
|
||||||
FileStatusCache &operator=(const FileStatusCache &) = delete;
|
FileStatusCache &operator=(const FileStatusCache &) = delete;
|
||||||
FileStatusCache(const FileStatusCache &) = delete;
|
FileStatusCache(const FileStatusCache &) = delete;
|
||||||
|
|
||||||
long long lastModifiedTime(ClangBackEnd::FilePathId filePathId) const;
|
long long lastModifiedTime(FilePathId filePathId) const;
|
||||||
void update(ClangBackEnd::FilePathId filePathId);
|
void update(FilePathId filePathId);
|
||||||
|
void update(FilePathIds filePathIds);
|
||||||
|
FilePathIds modified(FilePathIds filePathIds) const;
|
||||||
|
|
||||||
size_type size() const;
|
size_type size() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Internal::FileStatusCacheEntry findEntry(ClangBackEnd::FilePathId filePathId) const;
|
Internal::FileStatusCacheEntry findEntry(FilePathId filePathId) const;
|
||||||
QFileInfo qFileInfo(ClangBackEnd::FilePathId filePathId) const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
mutable Internal::FileStatusCacheEntries m_cacheEntries;
|
mutable Internal::FileStatusCacheEntries m_cacheEntries;
|
||||||
FilePathCachingInterface &m_filePathCache;
|
FileSystemInterface &m_fileSystem;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ClangBackEnd
|
} // namespace ClangBackEnd
|
61
src/libs/clangsupport/filesystem.cpp
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2019 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "filesystem.h"
|
||||||
|
#include "filepathcachinginterface.h"
|
||||||
|
|
||||||
|
#include <utils/algorithm.h>
|
||||||
|
|
||||||
|
#include <QDateTime>
|
||||||
|
#include <QDir>
|
||||||
|
#include <QFileInfo>
|
||||||
|
|
||||||
|
namespace ClangBackEnd {
|
||||||
|
|
||||||
|
FilePathIds FileSystem::directoryEntries(const QString &directoryPath) const
|
||||||
|
{
|
||||||
|
QDir directory{directoryPath};
|
||||||
|
|
||||||
|
QFileInfoList fileInfos = directory.entryInfoList();
|
||||||
|
|
||||||
|
FilePathIds filePathIds = Utils::transform<FilePathIds>(fileInfos, [&](const QFileInfo &fileInfo) {
|
||||||
|
return m_filePathCache.filePathId(FilePath{fileInfo.path()});
|
||||||
|
});
|
||||||
|
|
||||||
|
std::sort(filePathIds.begin(), filePathIds.end());
|
||||||
|
|
||||||
|
return filePathIds;
|
||||||
|
}
|
||||||
|
|
||||||
|
long long FileSystem::lastModified(FilePathId filePathId) const
|
||||||
|
{
|
||||||
|
QFileInfo fileInfo(QString(m_filePathCache.filePath(filePathId)));
|
||||||
|
|
||||||
|
fileInfo.refresh();
|
||||||
|
|
||||||
|
return fileInfo.lastModified().toMSecsSinceEpoch() / 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace ClangBackEnd
|
48
src/libs/clangsupport/filesystem.h
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2019 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "filestatuscache.h"
|
||||||
|
#include "filesysteminterface.h"
|
||||||
|
|
||||||
|
namespace ClangBackEnd {
|
||||||
|
class FilePathCachingInterface;
|
||||||
|
|
||||||
|
class CLANGSUPPORT_EXPORT FileSystem final : public FileSystemInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FileSystem(FilePathCachingInterface &filePathCache)
|
||||||
|
: m_filePathCache(filePathCache)
|
||||||
|
{}
|
||||||
|
|
||||||
|
FilePathIds directoryEntries(const QString &directoryPath) const override;
|
||||||
|
long long lastModified(FilePathId filePathId) const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
FilePathCachingInterface &m_filePathCache;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace ClangBackEnd
|
43
src/libs/clangsupport/filesysteminterface.h
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2019 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "filepathid.h"
|
||||||
|
|
||||||
|
#include <utils/smallstringview.h>
|
||||||
|
|
||||||
|
namespace ClangBackEnd {
|
||||||
|
|
||||||
|
class FileSystemInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual FilePathIds directoryEntries(const QString &directoryPath) const = 0;
|
||||||
|
virtual long long lastModified(FilePathId filePathId) const = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
~FileSystemInterface() = default;
|
||||||
|
};
|
||||||
|
} // namespace ClangBackEnd
|
@@ -25,23 +25,23 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "filepathcachinginterface.h"
|
#include "filesysteminterface.h"
|
||||||
#include "modifiedtimecheckerinterface.h"
|
#include "modifiedtimecheckerinterface.h"
|
||||||
|
#include "set_algorithm.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
|
|
||||||
namespace ClangBackEnd {
|
namespace ClangBackEnd {
|
||||||
|
|
||||||
template<typename SourceEntries = ::ClangBackEnd::SourceEntries>
|
template<typename SourceEntries = ::ClangBackEnd::SourceEntries>
|
||||||
class ModifiedTimeChecker final : public ModifiedTimeCheckerInterface<SourceEntries>
|
class ModifiedTimeChecker final : public ModifiedTimeCheckerInterface<SourceEntries>
|
||||||
{
|
{
|
||||||
using SourceEntry = typename SourceEntries::value_type;
|
using SourceEntry = typename SourceEntries::value_type;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using GetModifiedTime = std::function<ClangBackEnd::TimeStamp(ClangBackEnd::FilePathView filePath)>;
|
ModifiedTimeChecker(FileSystemInterface &fileSystem)
|
||||||
ModifiedTimeChecker(GetModifiedTime &getModifiedTime, FilePathCachingInterface &filePathCache)
|
: m_fileSystem(fileSystem)
|
||||||
: m_getModifiedTime(getModifiedTime)
|
|
||||||
, m_filePathCache(filePathCache)
|
|
||||||
{}
|
{}
|
||||||
|
|
||||||
bool isUpToDate(const SourceEntries &sourceEntries) const
|
bool isUpToDate(const SourceEntries &sourceEntries) const
|
||||||
@@ -51,165 +51,101 @@ public:
|
|||||||
|
|
||||||
updateCurrentSourceTimeStamps(sourceEntries);
|
updateCurrentSourceTimeStamps(sourceEntries);
|
||||||
|
|
||||||
return compareEntries(sourceEntries);
|
return compareEntries(sourceEntries) && notReseted(sourceEntries);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pathsChanged(const FilePathIds &filePathIds)
|
void pathsChanged(const FilePathIds &filePathIds) override
|
||||||
{
|
{
|
||||||
using SourceTimeStampReferences = std::vector<std::reference_wrapper<SourceTimeStamp>>;
|
|
||||||
|
|
||||||
SourceTimeStampReferences timeStampsToUpdate;
|
|
||||||
timeStampsToUpdate.reserve(filePathIds.size());
|
|
||||||
|
|
||||||
std::set_intersection(m_currentSourceTimeStamps.begin(),
|
std::set_intersection(m_currentSourceTimeStamps.begin(),
|
||||||
m_currentSourceTimeStamps.end(),
|
m_currentSourceTimeStamps.end(),
|
||||||
filePathIds.begin(),
|
filePathIds.begin(),
|
||||||
filePathIds.end(),
|
filePathIds.end(),
|
||||||
std::back_inserter(timeStampsToUpdate));
|
make_iterator([&](SourceTimeStamp &sourceTimeStamp) {
|
||||||
|
sourceTimeStamp.timeStamp = m_fileSystem.lastModified(
|
||||||
for (SourceTimeStamp &sourceTimeStamp : timeStampsToUpdate) {
|
sourceTimeStamp.sourceId);
|
||||||
sourceTimeStamp.timeStamp = m_getModifiedTime(
|
}));
|
||||||
m_filePathCache.filePath(sourceTimeStamp.sourceId));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void reset(const FilePathIds &filePathIds)
|
||||||
|
{
|
||||||
|
FilePathIds newResetFilePathIds;
|
||||||
|
newResetFilePathIds.reserve(newResetFilePathIds.size() + m_resetFilePathIds.size());
|
||||||
|
|
||||||
|
std::set_union(m_resetFilePathIds.begin(),
|
||||||
|
m_resetFilePathIds.end(),
|
||||||
|
filePathIds.begin(),
|
||||||
|
filePathIds.end(),
|
||||||
|
std::back_inserter(newResetFilePathIds));
|
||||||
|
|
||||||
|
m_resetFilePathIds = std::move(newResetFilePathIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool compareEntries(const SourceEntries &sourceEntries) const
|
bool compareEntries(const SourceEntries &sourceEntries) const
|
||||||
{
|
{
|
||||||
class CompareSourceId
|
return set_intersection_compare(
|
||||||
{
|
m_currentSourceTimeStamps.begin(),
|
||||||
public:
|
|
||||||
bool operator()(SourceTimeStamp first, SourceTimeStamp second)
|
|
||||||
{
|
|
||||||
return first.sourceId < second.sourceId;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator()(::ClangBackEnd::SourceEntry first, ::ClangBackEnd::SourceEntry second)
|
|
||||||
{
|
|
||||||
return first.sourceId < second.sourceId;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator()(SourceTimeStamp first, ::ClangBackEnd::SourceEntry second)
|
|
||||||
{
|
|
||||||
return first.sourceId < second.sourceId;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator()(::ClangBackEnd::SourceEntry first, SourceTimeStamp second)
|
|
||||||
{
|
|
||||||
return first.sourceId < second.sourceId;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
SourceTimeStamps currentSourceTimeStamp;
|
|
||||||
currentSourceTimeStamp.reserve(sourceEntries.size());
|
|
||||||
std::set_intersection(m_currentSourceTimeStamps.begin(),
|
|
||||||
m_currentSourceTimeStamps.end(),
|
m_currentSourceTimeStamps.end(),
|
||||||
sourceEntries.begin(),
|
sourceEntries.begin(),
|
||||||
sourceEntries.end(),
|
sourceEntries.end(),
|
||||||
std::back_inserter(currentSourceTimeStamp),
|
[](auto first, auto second) { return second.timeStamp > first.timeStamp; },
|
||||||
CompareSourceId{});
|
[](auto first, auto second) { return first.sourceId < second.sourceId; });
|
||||||
|
|
||||||
class CompareTime
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
bool operator()(SourceTimeStamp first, SourceTimeStamp second)
|
|
||||||
{
|
|
||||||
return first.timeStamp <= second.timeStamp;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator()(::ClangBackEnd::SourceEntry first, ::ClangBackEnd::SourceEntry second)
|
|
||||||
{
|
|
||||||
return first.timeStamp <= second.timeStamp;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator()(SourceTimeStamp first, ::ClangBackEnd::SourceEntry second)
|
|
||||||
{
|
|
||||||
return first.timeStamp <= second.timeStamp;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator()(::ClangBackEnd::SourceEntry first, SourceTimeStamp second)
|
|
||||||
{
|
|
||||||
return first.timeStamp <= second.timeStamp;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return std::lexicographical_compare(currentSourceTimeStamp.begin(),
|
|
||||||
currentSourceTimeStamp.end(),
|
|
||||||
sourceEntries.begin(),
|
|
||||||
sourceEntries.end(),
|
|
||||||
CompareTime{});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateCurrentSourceTimeStamps(const SourceEntries &sourceEntries) const
|
void updateCurrentSourceTimeStamps(const SourceEntries &sourceEntries) const
|
||||||
{
|
{
|
||||||
SourceTimeStamps sourceTimeStamps = newSourceTimeStamps(sourceEntries);
|
SourceTimeStamps sourceTimeStamps = newSourceTimeStamps(sourceEntries);
|
||||||
|
|
||||||
for (SourceTimeStamp &newSourceTimeStamp : sourceTimeStamps) {
|
|
||||||
newSourceTimeStamp.timeStamp = m_getModifiedTime(
|
|
||||||
m_filePathCache.filePath(newSourceTimeStamp.sourceId));
|
|
||||||
}
|
|
||||||
|
|
||||||
auto split = sourceTimeStamps.insert(sourceTimeStamps.end(),
|
auto split = sourceTimeStamps.insert(sourceTimeStamps.end(),
|
||||||
m_currentSourceTimeStamps.begin(),
|
m_currentSourceTimeStamps.begin(),
|
||||||
m_currentSourceTimeStamps.end());
|
m_currentSourceTimeStamps.end());
|
||||||
std::inplace_merge(sourceTimeStamps.begin(), split, sourceTimeStamps.end());
|
std::inplace_merge(sourceTimeStamps.begin(), split, sourceTimeStamps.end());
|
||||||
|
|
||||||
m_currentSourceTimeStamps = sourceTimeStamps;
|
m_currentSourceTimeStamps = std::move(sourceTimeStamps);
|
||||||
}
|
}
|
||||||
|
|
||||||
SourceTimeStamps newSourceTimeStamps(const SourceEntries &sourceEntries) const
|
SourceTimeStamps newSourceTimeStamps(const SourceEntries &sourceEntries) const
|
||||||
{
|
{
|
||||||
SourceEntries newSourceEntries;
|
SourceTimeStamps newTimeStamps;
|
||||||
newSourceEntries.reserve(sourceEntries.size());
|
newTimeStamps.reserve(sourceEntries.size());
|
||||||
|
|
||||||
class CompareSourceId
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
bool operator()(SourceTimeStamp first, SourceTimeStamp second)
|
|
||||||
{
|
|
||||||
return first.sourceId < second.sourceId;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator()(::ClangBackEnd::SourceEntry first, ::ClangBackEnd::SourceEntry second)
|
|
||||||
{
|
|
||||||
return first.sourceId < second.sourceId;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator()(SourceTimeStamp first, ::ClangBackEnd::SourceEntry second)
|
|
||||||
{
|
|
||||||
return first.sourceId < second.sourceId;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator()(::ClangBackEnd::SourceEntry first, SourceTimeStamp second)
|
|
||||||
{
|
|
||||||
return first.sourceId < second.sourceId;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
std::set_difference(sourceEntries.begin(),
|
std::set_difference(sourceEntries.begin(),
|
||||||
sourceEntries.end(),
|
sourceEntries.end(),
|
||||||
m_currentSourceTimeStamps.begin(),
|
m_currentSourceTimeStamps.begin(),
|
||||||
m_currentSourceTimeStamps.end(),
|
m_currentSourceTimeStamps.end(),
|
||||||
std::back_inserter(newSourceEntries),
|
make_iterator([&](const SourceEntry &sourceEntry) {
|
||||||
CompareSourceId{});
|
newTimeStamps.emplace_back(sourceEntry.sourceId,
|
||||||
|
m_fileSystem.lastModified(
|
||||||
SourceTimeStamps newTimeStamps;
|
sourceEntry.sourceId));
|
||||||
newTimeStamps.reserve(newSourceEntries.size());
|
}),
|
||||||
|
[](auto first, auto second) {
|
||||||
std::transform(newSourceEntries.begin(),
|
return first.sourceId < second.sourceId && first.timeStamp > 0;
|
||||||
newSourceEntries.end(),
|
|
||||||
std::back_inserter(newTimeStamps),
|
|
||||||
[](SourceEntry entry) {
|
|
||||||
return SourceTimeStamp{entry.sourceId, {}};
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return newTimeStamps;
|
return newTimeStamps;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool notReseted(const SourceEntries &sourceEntries) const
|
||||||
|
{
|
||||||
|
auto oldSize = m_resetFilePathIds.size();
|
||||||
|
FilePathIds newResetFilePathIds;
|
||||||
|
newResetFilePathIds.reserve(newResetFilePathIds.size());
|
||||||
|
|
||||||
|
std::set_difference(m_resetFilePathIds.begin(),
|
||||||
|
m_resetFilePathIds.end(),
|
||||||
|
sourceEntries.begin(),
|
||||||
|
sourceEntries.end(),
|
||||||
|
std::back_inserter(newResetFilePathIds));
|
||||||
|
|
||||||
|
m_resetFilePathIds = std::move(newResetFilePathIds);
|
||||||
|
|
||||||
|
return oldSize == m_resetFilePathIds.size();
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
mutable SourceTimeStamps m_currentSourceTimeStamps;
|
mutable SourceTimeStamps m_currentSourceTimeStamps;
|
||||||
GetModifiedTime &m_getModifiedTime;
|
mutable FilePathIds m_resetFilePathIds;
|
||||||
FilePathCachingInterface &m_filePathCache;
|
FileSystemInterface &m_fileSystem;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ClangBackEnd
|
} // namespace ClangBackEnd
|
||||||
|
@@ -38,6 +38,7 @@ public:
|
|||||||
ModifiedTimeCheckerInterface &operator=(const ModifiedTimeCheckerInterface &) = delete;
|
ModifiedTimeCheckerInterface &operator=(const ModifiedTimeCheckerInterface &) = delete;
|
||||||
|
|
||||||
virtual bool isUpToDate(const SourceEntries &sourceEntries) const = 0;
|
virtual bool isUpToDate(const SourceEntries &sourceEntries) const = 0;
|
||||||
|
virtual void pathsChanged(const FilePathIds &filePathIds) = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
~ModifiedTimeCheckerInterface() = default;
|
~ModifiedTimeCheckerInterface() = default;
|
||||||
|
@@ -144,11 +144,11 @@ public:
|
|||||||
table.setName("projectPartsFiles");
|
table.setName("projectPartsFiles");
|
||||||
const Sqlite::Column &projectPartIdColumn = table.addColumn("projectPartId", Sqlite::ColumnType::Integer);
|
const Sqlite::Column &projectPartIdColumn = table.addColumn("projectPartId", Sqlite::ColumnType::Integer);
|
||||||
const Sqlite::Column &sourceIdColumn = table.addColumn("sourceId", Sqlite::ColumnType::Integer);
|
const Sqlite::Column &sourceIdColumn = table.addColumn("sourceId", Sqlite::ColumnType::Integer);
|
||||||
table.addColumn("sourceType", Sqlite::ColumnType::Integer);
|
const Sqlite::Column &sourceType = table.addColumn("sourceType", Sqlite::ColumnType::Integer);
|
||||||
table.addColumn("pchCreationTimeStamp", Sqlite::ColumnType::Integer);
|
table.addColumn("pchCreationTimeStamp", Sqlite::ColumnType::Integer);
|
||||||
table.addColumn("hasMissingIncludes", Sqlite::ColumnType::Integer);
|
table.addColumn("hasMissingIncludes", Sqlite::ColumnType::Integer);
|
||||||
table.addUniqueIndex({sourceIdColumn, projectPartIdColumn});
|
table.addUniqueIndex({sourceIdColumn, projectPartIdColumn});
|
||||||
table.addIndex({projectPartIdColumn});
|
table.addIndex({projectPartIdColumn, sourceType});
|
||||||
|
|
||||||
table.initialize(database);
|
table.initialize(database);
|
||||||
}
|
}
|
||||||
|
101
src/libs/clangsupport/set_algorithm.h
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2019 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
namespace ClangBackEnd {
|
||||||
|
|
||||||
|
template<class Callable>
|
||||||
|
class function_output_iterator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef std::output_iterator_tag iterator_category;
|
||||||
|
typedef void value_type;
|
||||||
|
typedef void difference_type;
|
||||||
|
typedef void pointer;
|
||||||
|
typedef void reference;
|
||||||
|
|
||||||
|
explicit function_output_iterator() {}
|
||||||
|
|
||||||
|
explicit function_output_iterator(const Callable &callable)
|
||||||
|
: m_callable(&callable)
|
||||||
|
{}
|
||||||
|
|
||||||
|
function_output_iterator &operator=(const function_output_iterator &iterator)
|
||||||
|
{
|
||||||
|
m_callable = iterator.m_callable;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct helper
|
||||||
|
{
|
||||||
|
helper(const Callable *callable)
|
||||||
|
: m_callable(callable)
|
||||||
|
{}
|
||||||
|
template<class T>
|
||||||
|
helper &operator=(T &&value)
|
||||||
|
{
|
||||||
|
(*m_callable)(std::forward<T>(value));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
const Callable *m_callable;
|
||||||
|
};
|
||||||
|
|
||||||
|
helper operator*() { return helper(m_callable); }
|
||||||
|
function_output_iterator &operator++() { return *this; }
|
||||||
|
function_output_iterator &operator++(int) { return *this; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
const Callable *m_callable;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Callable>
|
||||||
|
function_output_iterator<Callable> make_iterator(const Callable &callable)
|
||||||
|
{
|
||||||
|
return function_output_iterator<Callable>(callable);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class InputIt1, class InputIt2, class Callable, class Compare>
|
||||||
|
bool set_intersection_compare(
|
||||||
|
InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2, Callable call, Compare comp)
|
||||||
|
{
|
||||||
|
while (first1 != last1 && first2 != last2) {
|
||||||
|
if (comp(*first1, *first2)) {
|
||||||
|
++first1;
|
||||||
|
} else {
|
||||||
|
if (!comp(*first2, *first1)) {
|
||||||
|
if (call(*first2, *first1++))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
++first2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} // namespace ClangBackEnd
|
@@ -131,6 +131,10 @@ public:
|
|||||||
return first.sourceId < second.sourceId;
|
return first.sourceId < second.sourceId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
friend bool operator<(SourceEntry first, FilePathId second) { return first.sourceId < second; }
|
||||||
|
|
||||||
|
friend bool operator<(FilePathId first, SourceEntry second) { return first < second.sourceId; }
|
||||||
|
|
||||||
friend bool operator==(SourceEntry first, SourceEntry second)
|
friend bool operator==(SourceEntry first, SourceEntry second)
|
||||||
{
|
{
|
||||||
return first.sourceId == second.sourceId && first.sourceType == second.sourceType
|
return first.sourceId == second.sourceId && first.sourceType == second.sourceType
|
||||||
|
@@ -92,7 +92,7 @@ using ResponseHandler = std::function<void(const QByteArray &, QTextCodec *)>;
|
|||||||
using ResponseHandlers = std::function<void(MessageId, const QByteArray &, QTextCodec *)>;
|
using ResponseHandlers = std::function<void(MessageId, const QByteArray &, QTextCodec *)>;
|
||||||
using MethodHandler = std::function<void(const QString, MessageId, const IContent *)>;
|
using MethodHandler = std::function<void(const QString, MessageId, const IContent *)>;
|
||||||
|
|
||||||
inline LANGUAGESERVERPROTOCOL_EXPORT uint qHash(const LanguageServerProtocol::MessageId &id)
|
inline uint qHash(const LanguageServerProtocol::MessageId &id)
|
||||||
{
|
{
|
||||||
if (Utils::holds_alternative<int>(id))
|
if (Utils::holds_alternative<int>(id))
|
||||||
return QT_PREPEND_NAMESPACE(qHash(Utils::get<int>(id)));
|
return QT_PREPEND_NAMESPACE(qHash(Utils::get<int>(id)));
|
||||||
@@ -102,8 +102,7 @@ inline LANGUAGESERVERPROTOCOL_EXPORT uint qHash(const LanguageServerProtocol::Me
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename Error>
|
template <typename Error>
|
||||||
inline LANGUAGESERVERPROTOCOL_EXPORT QDebug operator<<(QDebug stream,
|
inline QDebug operator<<(QDebug stream, const LanguageServerProtocol::MessageId &id)
|
||||||
const LanguageServerProtocol::MessageId &id)
|
|
||||||
{
|
{
|
||||||
if (Utils::holds_alternative<int>(id))
|
if (Utils::holds_alternative<int>(id))
|
||||||
stream << Utils::get<int>(id);
|
stream << Utils::get<int>(id);
|
||||||
|
@@ -1676,7 +1676,7 @@ bool Check::visit(CallExpression *ast)
|
|||||||
if (!whiteListedFunction && !isMathFunction && !isDateFunction && !isDirectInConnectionsScope)
|
if (!whiteListedFunction && !isMathFunction && !isDateFunction && !isDirectInConnectionsScope)
|
||||||
addMessage(ErrFunctionsNotSupportedInQmlUi, location);
|
addMessage(ErrFunctionsNotSupportedInQmlUi, location);
|
||||||
|
|
||||||
static const QStringList globalFunctions = {"String", "Boolean", "Date", "Number", "Object", "QT_TR_NOOP", "QT_TRANSLATE_NOOP", "QT_TRID_NOOP"};
|
static const QStringList globalFunctions = {"String", "Boolean", "Date", "Number", "Object", "Array", "QT_TR_NOOP", "QT_TRANSLATE_NOOP", "QT_TRID_NOOP"};
|
||||||
|
|
||||||
if (!name.isEmpty() && name.at(0).isUpper() && !globalFunctions.contains(name)) {
|
if (!name.isEmpty() && name.at(0).isUpper() && !globalFunctions.contains(name)) {
|
||||||
addMessage(WarnExpectedNewWithUppercaseFunction, location);
|
addMessage(WarnExpectedNewWithUppercaseFunction, location);
|
||||||
|
@@ -179,6 +179,10 @@ public:
|
|||||||
return m_pointer[0] == characterToSearch;
|
return m_pointer[0] == characterToSearch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char back() const { return m_pointer[m_size - 1]; }
|
||||||
|
|
||||||
|
char operator[](std::size_t index) { return m_pointer[index]; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const char *m_pointer = "";
|
const char *m_pointer = "";
|
||||||
size_type m_size = 0;
|
size_type m_size = 0;
|
||||||
|
@@ -77,8 +77,9 @@ void AutoTestUnitTests::initTestCase()
|
|||||||
if (!qgetenv("BOOST_INCLUDE_DIR").isEmpty()) {
|
if (!qgetenv("BOOST_INCLUDE_DIR").isEmpty()) {
|
||||||
m_checkBoost = true;
|
m_checkBoost = true;
|
||||||
} else {
|
} else {
|
||||||
if (QFileInfo::exists("/usr/include/boost/version.hpp")
|
if (Utils::HostOsInfo::isLinuxHost()
|
||||||
|| QFileInfo::exists("/usr/local/include/boost/version.hpp")) {
|
&& (QFileInfo::exists("/usr/include/boost/version.hpp")
|
||||||
|
|| QFileInfo::exists("/usr/local/include/boost/version.hpp"))) {
|
||||||
qDebug() << "Found boost at system level - will run boost parser test.";
|
qDebug() << "Found boost at system level - will run boost parser test.";
|
||||||
m_checkBoost = true;
|
m_checkBoost = true;
|
||||||
}
|
}
|
||||||
|
@@ -37,6 +37,7 @@ enum class ReportLevel;
|
|||||||
|
|
||||||
class BoostTestOutputReader : public TestOutputReader
|
class BoostTestOutputReader : public TestOutputReader
|
||||||
{
|
{
|
||||||
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
BoostTestOutputReader(const QFutureInterface<TestResultPtr> &futureInterface,
|
BoostTestOutputReader(const QFutureInterface<TestResultPtr> &futureInterface,
|
||||||
QProcess *testApplication, const QString &buildDirectory,
|
QProcess *testApplication, const QString &buildDirectory,
|
||||||
|
@@ -411,9 +411,9 @@ QList<ToolChain *> IarToolChainFactory::autoDetect(const QList<ToolChain *> &alr
|
|||||||
QString registryKey;
|
QString registryKey;
|
||||||
QString subExePath;
|
QString subExePath;
|
||||||
} knowToolchains[] = {
|
} knowToolchains[] = {
|
||||||
{"EWARM", "\\arm\\bin\\iccarm.exe"},
|
{{"EWARM"}, {"\\arm\\bin\\iccarm.exe"}},
|
||||||
{"EWAVR", "\\avr\\bin\\iccavr.exe"},
|
{{"EWAVR"}, {"\\avr\\bin\\iccavr.exe"}},
|
||||||
{"EW8051", "\\8051\\bin\\icc8051.exe"},
|
{{"EW8051"}, {"\\8051\\bin\\icc8051.exe"}},
|
||||||
};
|
};
|
||||||
|
|
||||||
QSettings registry(kRegistryNode, QSettings::NativeFormat);
|
QSettings registry(kRegistryNode, QSettings::NativeFormat);
|
||||||
|
@@ -144,7 +144,7 @@ void ClangCodeModelPlugin::createCompilationDBButton()
|
|||||||
message = tr("Clang compilation database generated at \"%1\".")
|
message = tr("Clang compilation database generated at \"%1\".")
|
||||||
.arg(QDir::toNativeSeparators(result.filePath));
|
.arg(QDir::toNativeSeparators(result.filePath));
|
||||||
} else {
|
} else {
|
||||||
message = tr("Generating clang compilation database failed: %1").arg(result.error);
|
message = tr("Generating Clang compilation database failed: %1").arg(result.error);
|
||||||
}
|
}
|
||||||
Core::MessageManager::write(message, Core::MessageManager::Flash);
|
Core::MessageManager::write(message, Core::MessageManager::Flash);
|
||||||
m_generateCompilationDBAction->setEnabled(
|
m_generateCompilationDBAction->setEnabled(
|
||||||
|
@@ -295,6 +295,7 @@ SelectableFilesDialog::SelectableFilesDialog(const ProjectInfo &projectInfo,
|
|||||||
CppTools::ClangDiagnosticConfigsSelectionWidget *diagnosticConfigsSelectionWidget
|
CppTools::ClangDiagnosticConfigsSelectionWidget *diagnosticConfigsSelectionWidget
|
||||||
= m_ui->clangToolsBasicSettings->ui()->clangDiagnosticConfigsSelectionWidget;
|
= m_ui->clangToolsBasicSettings->ui()->clangDiagnosticConfigsSelectionWidget;
|
||||||
QCheckBox *buildBeforeAnalysis = m_ui->clangToolsBasicSettings->ui()->buildBeforeAnalysis;
|
QCheckBox *buildBeforeAnalysis = m_ui->clangToolsBasicSettings->ui()->buildBeforeAnalysis;
|
||||||
|
buildBeforeAnalysis->setToolTip(hintAboutBuildBeforeAnalysis());
|
||||||
|
|
||||||
ClangToolsProjectSettings *settings = ClangToolsProjectSettingsManager::getSettings(m_project);
|
ClangToolsProjectSettings *settings = ClangToolsProjectSettingsManager::getSettings(m_project);
|
||||||
m_customDiagnosticConfig = diagnosticConfiguration(settings);
|
m_customDiagnosticConfig = diagnosticConfiguration(settings);
|
||||||
@@ -337,6 +338,8 @@ SelectableFilesDialog::SelectableFilesDialog(const ProjectInfo &projectInfo,
|
|||||||
m_customDiagnosticConfig = currentConfigId;
|
m_customDiagnosticConfig = currentConfigId;
|
||||||
});
|
});
|
||||||
connect(buildBeforeAnalysis, &QCheckBox::toggled, [this](bool checked) {
|
connect(buildBeforeAnalysis, &QCheckBox::toggled, [this](bool checked) {
|
||||||
|
if (!checked)
|
||||||
|
showHintAboutBuildBeforeAnalysis();
|
||||||
if (m_ui->globalOrCustom->currentIndex() == CustomSettings)
|
if (m_ui->globalOrCustom->currentIndex() == CustomSettings)
|
||||||
m_buildBeforeAnalysis = checked;
|
m_buildBeforeAnalysis = checked;
|
||||||
});
|
});
|
||||||
|
@@ -477,6 +477,16 @@ void ClangToolRunControl::finalize()
|
|||||||
if (m_filesNotAnalyzed != 0) {
|
if (m_filesNotAnalyzed != 0) {
|
||||||
QString msg = tr("%1: Not all files could be analyzed.").arg(toolName);
|
QString msg = tr("%1: Not all files could be analyzed.").arg(toolName);
|
||||||
TaskHub::addTask(Task::Error, msg, Debugger::Constants::ANALYZERTASK_ID);
|
TaskHub::addTask(Task::Error, msg, Debugger::Constants::ANALYZERTASK_ID);
|
||||||
|
if (m_target && !m_target->activeBuildConfiguration()->buildDirectory().exists()
|
||||||
|
&& !ClangToolsProjectSettingsManager::getSettings(m_target->project())
|
||||||
|
->buildBeforeAnalysis()) {
|
||||||
|
msg = tr("%1: You might need to build the project to generate or update source "
|
||||||
|
"files. To build automatically, enable \"Build the project before starting "
|
||||||
|
"analysis\".")
|
||||||
|
.arg(toolName);
|
||||||
|
TaskHub::addTask(Task::Error, msg, Debugger::Constants::ANALYZERTASK_ID);
|
||||||
|
}
|
||||||
|
|
||||||
TaskHub::requestPopup();
|
TaskHub::requestPopup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -56,9 +56,12 @@ ClangToolsConfigWidget::ClangToolsConfigWidget(
|
|||||||
[settings](int count) { settings->setSimultaneousProcesses(count); });
|
[settings](int count) { settings->setSimultaneousProcesses(count); });
|
||||||
|
|
||||||
QCheckBox *buildBeforeAnalysis = m_ui->clangToolsBasicSettings->ui()->buildBeforeAnalysis;
|
QCheckBox *buildBeforeAnalysis = m_ui->clangToolsBasicSettings->ui()->buildBeforeAnalysis;
|
||||||
|
buildBeforeAnalysis->setToolTip(hintAboutBuildBeforeAnalysis());
|
||||||
buildBeforeAnalysis->setCheckState(settings->savedBuildBeforeAnalysis()
|
buildBeforeAnalysis->setCheckState(settings->savedBuildBeforeAnalysis()
|
||||||
? Qt::Checked : Qt::Unchecked);
|
? Qt::Checked : Qt::Unchecked);
|
||||||
connect(buildBeforeAnalysis, &QCheckBox::toggled, [settings](bool checked) {
|
connect(buildBeforeAnalysis, &QCheckBox::toggled, [settings](bool checked) {
|
||||||
|
if (!checked)
|
||||||
|
showHintAboutBuildBeforeAnalysis();
|
||||||
settings->setBuildBeforeAnalysis(checked);
|
settings->setBuildBeforeAnalysis(checked);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@@ -87,7 +87,9 @@ void ClangToolsProjectSettings::load()
|
|||||||
m_useGlobalSettings = useGlobalVariant.isValid() ? useGlobalVariant.toBool() : true;
|
m_useGlobalSettings = useGlobalVariant.isValid() ? useGlobalVariant.toBool() : true;
|
||||||
m_diagnosticConfig = Core::Id::fromSetting(
|
m_diagnosticConfig = Core::Id::fromSetting(
|
||||||
m_project->namedSettings(SETTINGS_KEY_DIAGNOSTIC_CONFIG));
|
m_project->namedSettings(SETTINGS_KEY_DIAGNOSTIC_CONFIG));
|
||||||
m_buildBeforeAnalysis = m_project->namedSettings(SETTINGS_KEY_BUILD_BEFORE_ANALYSIS).toBool();
|
|
||||||
|
const QVariant value = m_project->namedSettings(SETTINGS_KEY_BUILD_BEFORE_ANALYSIS);
|
||||||
|
m_buildBeforeAnalysis = value.isValid() ? value.toBool() : true;
|
||||||
|
|
||||||
auto toFileName = [](const QString &s) { return Utils::FilePath::fromString(s); };
|
auto toFileName = [](const QString &s) { return Utils::FilePath::fromString(s); };
|
||||||
|
|
||||||
|
@@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
#include "clangtoolsutils.h"
|
#include "clangtoolsutils.h"
|
||||||
|
|
||||||
|
#include "clangtool.h"
|
||||||
#include "clangtoolsdiagnostic.h"
|
#include "clangtoolsdiagnostic.h"
|
||||||
#include "clangtoolssettings.h"
|
#include "clangtoolssettings.h"
|
||||||
|
|
||||||
@@ -32,8 +33,9 @@
|
|||||||
|
|
||||||
#include <projectexplorer/projectexplorerconstants.h>
|
#include <projectexplorer/projectexplorerconstants.h>
|
||||||
|
|
||||||
#include <utils/hostosinfo.h>
|
#include <utils/checkablemessagebox.h>
|
||||||
#include <utils/environment.h>
|
#include <utils/environment.h>
|
||||||
|
#include <utils/hostosinfo.h>
|
||||||
#include <utils/synchronousprocess.h>
|
#include <utils/synchronousprocess.h>
|
||||||
|
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
@@ -49,5 +51,24 @@ QString createFullLocationString(const Debugger::DiagnosticLocation &location)
|
|||||||
+ QLatin1Char(':') + QString::number(location.column);
|
+ QLatin1Char(':') + QString::number(location.column);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString hintAboutBuildBeforeAnalysis()
|
||||||
|
{
|
||||||
|
return ClangTool::tr(
|
||||||
|
"In general, the project should be built before starting the analysis to ensure that the "
|
||||||
|
"code to analyze is valid.<br/><br/>"
|
||||||
|
"Building the project might also run code generators that update the source files as "
|
||||||
|
"necessary.");
|
||||||
|
}
|
||||||
|
|
||||||
|
void showHintAboutBuildBeforeAnalysis()
|
||||||
|
{
|
||||||
|
Utils::CheckableMessageBox::doNotShowAgainInformation(
|
||||||
|
Core::ICore::dialogParent(),
|
||||||
|
ClangTool::tr("Info About Build the Project Before Analysis"),
|
||||||
|
hintAboutBuildBeforeAnalysis(),
|
||||||
|
Core::ICore::settings(),
|
||||||
|
"ClangToolsDisablingBuildBeforeAnalysisHint");
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
} // namespace ClangTools
|
} // namespace ClangTools
|
||||||
|
@@ -41,5 +41,8 @@ namespace Internal {
|
|||||||
|
|
||||||
QString createFullLocationString(const Debugger::DiagnosticLocation &location);
|
QString createFullLocationString(const Debugger::DiagnosticLocation &location);
|
||||||
|
|
||||||
|
QString hintAboutBuildBeforeAnalysis();
|
||||||
|
void showHintAboutBuildBeforeAnalysis();
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
} // namespace ClangTools
|
} // namespace ClangTools
|
||||||
|
@@ -2429,12 +2429,12 @@ void EditorManager::closeOtherDocuments(IDocument *document)
|
|||||||
closeDocuments(documentsToClose, true);
|
closeDocuments(documentsToClose, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EditorManager::closeAllDocuments()
|
bool EditorManager::closeAllDocuments()
|
||||||
{
|
{
|
||||||
// Only close the files that aren't pinned.
|
// Only close the files that aren't pinned.
|
||||||
const QList<DocumentModel::Entry *> entriesToClose
|
const QList<DocumentModel::Entry *> entriesToClose
|
||||||
= Utils::filtered(DocumentModel::entries(), Utils::equal(&DocumentModel::Entry::pinned, false));
|
= Utils::filtered(DocumentModel::entries(), Utils::equal(&DocumentModel::Entry::pinned, false));
|
||||||
EditorManager::closeDocuments(entriesToClose);
|
return EditorManager::closeDocuments(entriesToClose);
|
||||||
}
|
}
|
||||||
|
|
||||||
// SLOT connected to action
|
// SLOT connected to action
|
||||||
@@ -2631,7 +2631,7 @@ void EditorManager::closeDocument(DocumentModel::Entry *entry)
|
|||||||
closeDocuments({entry->document});
|
closeDocuments({entry->document});
|
||||||
}
|
}
|
||||||
|
|
||||||
void EditorManager::closeDocuments(const QList<DocumentModel::Entry *> &entries)
|
bool EditorManager::closeDocuments(const QList<DocumentModel::Entry *> &entries)
|
||||||
{
|
{
|
||||||
QList<IDocument *> documentsToClose;
|
QList<IDocument *> documentsToClose;
|
||||||
for (DocumentModel::Entry *entry : entries) {
|
for (DocumentModel::Entry *entry : entries) {
|
||||||
@@ -2642,7 +2642,7 @@ void EditorManager::closeDocuments(const QList<DocumentModel::Entry *> &entries)
|
|||||||
else
|
else
|
||||||
documentsToClose << entry->document;
|
documentsToClose << entry->document;
|
||||||
}
|
}
|
||||||
closeDocuments(documentsToClose);
|
return closeDocuments(documentsToClose);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EditorManager::closeEditors(const QList<IEditor*> &editorsToClose, bool askAboutModifiedEditors)
|
bool EditorManager::closeEditors(const QList<IEditor*> &editorsToClose, bool askAboutModifiedEditors)
|
||||||
|
@@ -128,9 +128,9 @@ public:
|
|||||||
static bool closeDocument(IDocument *document, bool askAboutModifiedEditors = true);
|
static bool closeDocument(IDocument *document, bool askAboutModifiedEditors = true);
|
||||||
static bool closeDocuments(const QList<IDocument *> &documents, bool askAboutModifiedEditors = true);
|
static bool closeDocuments(const QList<IDocument *> &documents, bool askAboutModifiedEditors = true);
|
||||||
static void closeDocument(DocumentModel::Entry *entry);
|
static void closeDocument(DocumentModel::Entry *entry);
|
||||||
static void closeDocuments(const QList<DocumentModel::Entry *> &entries);
|
static bool closeDocuments(const QList<DocumentModel::Entry *> &entries);
|
||||||
static void closeOtherDocuments(IDocument *document);
|
static void closeOtherDocuments(IDocument *document);
|
||||||
static void closeAllDocuments();
|
static bool closeAllDocuments();
|
||||||
|
|
||||||
static void addCurrentPositionToNavigationHistory(const QByteArray &saveState = QByteArray());
|
static void addCurrentPositionToNavigationHistory(const QByteArray &saveState = QByteArray());
|
||||||
static void cutForwardNavigationHistory();
|
static void cutForwardNavigationHistory();
|
||||||
|
@@ -79,7 +79,6 @@ public:
|
|||||||
bool hasWriteWarning = false;
|
bool hasWriteWarning = false;
|
||||||
bool restored = false;
|
bool restored = false;
|
||||||
bool isSuspendAllowed = false;
|
bool isSuspendAllowed = false;
|
||||||
bool pinned = false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
@@ -41,6 +41,8 @@ class QWidget;
|
|||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
namespace Core {
|
namespace Core {
|
||||||
|
class CommandButton;
|
||||||
|
class IContext;
|
||||||
|
|
||||||
class CORE_EXPORT IOutputPane : public QObject
|
class CORE_EXPORT IOutputPane : public QObject
|
||||||
{
|
{
|
||||||
@@ -93,6 +95,7 @@ signals:
|
|||||||
void setBadgeNumber(int number);
|
void setBadgeNumber(int number);
|
||||||
void zoomIn(int range);
|
void zoomIn(int range);
|
||||||
void zoomOut(int range);
|
void zoomOut(int range);
|
||||||
|
void resetZoom();
|
||||||
void wheelZoomEnabledChanged(bool enabled);
|
void wheelZoomEnabledChanged(bool enabled);
|
||||||
void fontChanged(const QFont &font);
|
void fontChanged(const QFont &font);
|
||||||
|
|
||||||
@@ -103,7 +106,7 @@ protected:
|
|||||||
Qt::CaseSensitivity filterCaseSensitivity() const { return m_filterCaseSensitivity; }
|
Qt::CaseSensitivity filterCaseSensitivity() const { return m_filterCaseSensitivity; }
|
||||||
void setFilteringEnabled(bool enable);
|
void setFilteringEnabled(bool enable);
|
||||||
QWidget *filterWidget() const { return m_filterOutputLineEdit; }
|
QWidget *filterWidget() const { return m_filterOutputLineEdit; }
|
||||||
|
void setupContext(const char *context, QWidget *widget);
|
||||||
void setZoomButtonsEnabled(bool enabled);
|
void setZoomButtonsEnabled(bool enabled);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -115,11 +118,12 @@ private:
|
|||||||
Id filterRegexpActionId() const;
|
Id filterRegexpActionId() const;
|
||||||
Id filterCaseSensitivityActionId() const;
|
Id filterCaseSensitivityActionId() const;
|
||||||
|
|
||||||
QToolButton * const m_zoomInButton = nullptr;
|
Core::CommandButton * const m_zoomInButton;
|
||||||
QToolButton * const m_zoomOutButton = nullptr;
|
Core::CommandButton * const m_zoomOutButton;
|
||||||
QAction *m_filterActionRegexp = nullptr;
|
QAction *m_filterActionRegexp = nullptr;
|
||||||
QAction *m_filterActionCaseSensitive = nullptr;
|
QAction *m_filterActionCaseSensitive = nullptr;
|
||||||
Utils::FancyLineEdit *m_filterOutputLineEdit = nullptr;
|
Utils::FancyLineEdit *m_filterOutputLineEdit = nullptr;
|
||||||
|
IContext *m_context = nullptr;
|
||||||
bool m_filterRegexp = false;
|
bool m_filterRegexp = false;
|
||||||
Qt::CaseSensitivity m_filterCaseSensitivity = Qt::CaseInsensitive;
|
Qt::CaseSensitivity m_filterCaseSensitivity = Qt::CaseInsensitive;
|
||||||
};
|
};
|
||||||
|
@@ -56,6 +56,7 @@ MessageOutputWindow::MessageOutputWindow()
|
|||||||
|
|
||||||
connect(this, &IOutputPane::zoomIn, m_widget, &Core::OutputWindow::zoomIn);
|
connect(this, &IOutputPane::zoomIn, m_widget, &Core::OutputWindow::zoomIn);
|
||||||
connect(this, &IOutputPane::zoomOut, m_widget, &Core::OutputWindow::zoomOut);
|
connect(this, &IOutputPane::zoomOut, m_widget, &Core::OutputWindow::zoomOut);
|
||||||
|
connect(this, &IOutputPane::resetZoom, m_widget, &Core::OutputWindow::resetZoom);
|
||||||
connect(this, &IOutputPane::fontChanged, m_widget, &OutputWindow::setBaseFont);
|
connect(this, &IOutputPane::fontChanged, m_widget, &OutputWindow::setBaseFont);
|
||||||
connect(this, &IOutputPane::wheelZoomEnabledChanged, m_widget, &OutputWindow::setWheelZoomEnabled);
|
connect(this, &IOutputPane::wheelZoomEnabledChanged, m_widget, &OutputWindow::setWheelZoomEnabled);
|
||||||
|
|
||||||
@@ -65,6 +66,7 @@ MessageOutputWindow::MessageOutputWindow()
|
|||||||
|
|
||||||
setupFilterUi("MessageOutputPane.Filter");
|
setupFilterUi("MessageOutputPane.Filter");
|
||||||
setFilteringEnabled(true);
|
setFilteringEnabled(true);
|
||||||
|
setupContext(Constants::C_GENERAL_OUTPUT_PANE, m_widget);
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageOutputWindow::~MessageOutputWindow()
|
MessageOutputWindow::~MessageOutputWindow()
|
||||||
|
@@ -35,6 +35,7 @@
|
|||||||
#include <coreplugin/actionmanager/actionmanager.h>
|
#include <coreplugin/actionmanager/actionmanager.h>
|
||||||
#include <coreplugin/actionmanager/actioncontainer.h>
|
#include <coreplugin/actionmanager/actioncontainer.h>
|
||||||
#include <coreplugin/actionmanager/command.h>
|
#include <coreplugin/actionmanager/command.h>
|
||||||
|
#include <coreplugin/actionmanager/commandbutton.h>
|
||||||
#include <coreplugin/editormanager/editormanager.h>
|
#include <coreplugin/editormanager/editormanager.h>
|
||||||
#include <coreplugin/editormanager/ieditor.h>
|
#include <coreplugin/editormanager/ieditor.h>
|
||||||
#include <coreplugin/find/optionspopup.h>
|
#include <coreplugin/find/optionspopup.h>
|
||||||
@@ -90,24 +91,27 @@ static bool g_managerConstructed = false; // For debugging reasons.
|
|||||||
|
|
||||||
IOutputPane::IOutputPane(QObject *parent)
|
IOutputPane::IOutputPane(QObject *parent)
|
||||||
: QObject(parent),
|
: QObject(parent),
|
||||||
m_zoomInButton(new QToolButton),
|
m_zoomInButton(new Core::CommandButton),
|
||||||
m_zoomOutButton(new QToolButton)
|
m_zoomOutButton(new Core::CommandButton)
|
||||||
{
|
{
|
||||||
// We need all pages first. Ignore latecomers and shout.
|
// We need all pages first. Ignore latecomers and shout.
|
||||||
QTC_ASSERT(!g_managerConstructed, return);
|
QTC_ASSERT(!g_managerConstructed, return);
|
||||||
g_outputPanes.append(OutputPaneData(this));
|
g_outputPanes.append(OutputPaneData(this));
|
||||||
|
|
||||||
m_zoomInButton->setToolTip(tr("Increase Font Size"));
|
|
||||||
m_zoomInButton->setIcon(Utils::Icons::PLUS_TOOLBAR.icon());
|
m_zoomInButton->setIcon(Utils::Icons::PLUS_TOOLBAR.icon());
|
||||||
|
m_zoomInButton->setCommandId(Constants::ZOOM_IN);
|
||||||
connect(m_zoomInButton, &QToolButton::clicked, this, [this] { emit zoomIn(1); });
|
connect(m_zoomInButton, &QToolButton::clicked, this, [this] { emit zoomIn(1); });
|
||||||
|
|
||||||
m_zoomOutButton->setToolTip(tr("Decrease Font Size"));
|
|
||||||
m_zoomOutButton->setIcon(Utils::Icons::MINUS.icon());
|
m_zoomOutButton->setIcon(Utils::Icons::MINUS.icon());
|
||||||
|
m_zoomOutButton->setCommandId(Constants::ZOOM_OUT);
|
||||||
connect(m_zoomOutButton, &QToolButton::clicked, this, [this] { emit zoomOut(1); });
|
connect(m_zoomOutButton, &QToolButton::clicked, this, [this] { emit zoomOut(1); });
|
||||||
}
|
}
|
||||||
|
|
||||||
IOutputPane::~IOutputPane()
|
IOutputPane::~IOutputPane()
|
||||||
{
|
{
|
||||||
|
if (m_context)
|
||||||
|
ICore::removeContextObject(m_context);
|
||||||
|
|
||||||
const int i = Utils::indexOf(g_outputPanes, Utils::equal(&OutputPaneData::pane, this));
|
const int i = Utils::indexOf(g_outputPanes, Utils::equal(&OutputPaneData::pane, this));
|
||||||
QTC_ASSERT(i >= 0, return);
|
QTC_ASSERT(i >= 0, return);
|
||||||
delete g_outputPanes.at(i).button;
|
delete g_outputPanes.at(i).button;
|
||||||
@@ -174,6 +178,26 @@ void IOutputPane::setFilteringEnabled(bool enable)
|
|||||||
m_filterOutputLineEdit->setEnabled(enable);
|
m_filterOutputLineEdit->setEnabled(enable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IOutputPane::setupContext(const char *context, QWidget *widget)
|
||||||
|
{
|
||||||
|
QTC_ASSERT(!m_context, return);
|
||||||
|
m_context = new IContext(this);
|
||||||
|
m_context->setContext(Context(context));
|
||||||
|
m_context->setWidget(widget);
|
||||||
|
ICore::addContextObject(m_context);
|
||||||
|
|
||||||
|
const auto zoomInAction = new QAction(this);
|
||||||
|
Core::ActionManager::registerAction(zoomInAction, Constants::ZOOM_IN, m_context->context());
|
||||||
|
connect(zoomInAction, &QAction::triggered, this, [this] { emit zoomIn(1); });
|
||||||
|
const auto zoomOutAction = new QAction(this);
|
||||||
|
Core::ActionManager::registerAction(zoomOutAction, Constants::ZOOM_OUT, m_context->context());
|
||||||
|
connect(zoomOutAction, &QAction::triggered, this, [this] { emit zoomOut(1); });
|
||||||
|
const auto resetZoomAction = new QAction(this);
|
||||||
|
Core::ActionManager::registerAction(resetZoomAction, Constants::ZOOM_RESET,
|
||||||
|
m_context->context());
|
||||||
|
connect(resetZoomAction, &QAction::triggered, this, &IOutputPane::resetZoom);
|
||||||
|
}
|
||||||
|
|
||||||
void IOutputPane::setZoomButtonsEnabled(bool enabled)
|
void IOutputPane::setZoomButtonsEnabled(bool enabled)
|
||||||
{
|
{
|
||||||
m_zoomInButton->setEnabled(enabled);
|
m_zoomInButton->setEnabled(enabled);
|
||||||
|
@@ -75,6 +75,7 @@ public:
|
|||||||
void setBaseFont(const QFont &newFont);
|
void setBaseFont(const QFont &newFont);
|
||||||
float fontZoom() const;
|
float fontZoom() const;
|
||||||
void setFontZoom(float zoom);
|
void setFontZoom(float zoom);
|
||||||
|
void resetZoom() { setFontZoom(0); }
|
||||||
void setWheelZoomEnabled(bool enabled);
|
void setWheelZoomEnabled(bool enabled);
|
||||||
|
|
||||||
void updateFilterProperties(const QString &filterText, Qt::CaseSensitivity caseSensitivity, bool regexp);
|
void updateFilterProperties(const QString &filterText, Qt::CaseSensitivity caseSensitivity, bool regexp);
|
||||||
|
@@ -111,14 +111,16 @@ QString ParseContextModel::currentId() const
|
|||||||
return m_projectParts[m_currentIndex]->id();
|
return m_projectParts[m_currentIndex]->id();
|
||||||
}
|
}
|
||||||
|
|
||||||
int ParseContextModel::rowCount(const QModelIndex &) const
|
int ParseContextModel::rowCount(const QModelIndex &parent) const
|
||||||
{
|
{
|
||||||
|
if (parent.isValid())
|
||||||
|
return 0;
|
||||||
return m_projectParts.size();
|
return m_projectParts.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant ParseContextModel::data(const QModelIndex &index, int role) const
|
QVariant ParseContextModel::data(const QModelIndex &index, int role) const
|
||||||
{
|
{
|
||||||
if (m_projectParts.isEmpty())
|
if (!index.isValid() || index.row() < 0 || index.row() >= m_projectParts.size())
|
||||||
return QVariant();
|
return QVariant();
|
||||||
|
|
||||||
const int row = index.row();
|
const int row = index.row();
|
||||||
|
@@ -709,6 +709,7 @@ void CompilerOptionsBuilder::evaluateCompilerFlags()
|
|||||||
qgetenv("QTC_CLANG_CMD_OPTIONS_BLACKLIST"))
|
qgetenv("QTC_CLANG_CMD_OPTIONS_BLACKLIST"))
|
||||||
.split(';', QString::SkipEmptyParts);
|
.split(';', QString::SkipEmptyParts);
|
||||||
|
|
||||||
|
const Core::Id &toolChain = m_projectPart.toolchainType;
|
||||||
bool containsDriverMode = false;
|
bool containsDriverMode = false;
|
||||||
bool skipNext = false;
|
bool skipNext = false;
|
||||||
for (const QString &option : m_projectPart.compilerFlags) {
|
for (const QString &option : m_projectPart.compilerFlags) {
|
||||||
@@ -720,6 +721,13 @@ void CompilerOptionsBuilder::evaluateCompilerFlags()
|
|||||||
if (userBlackList.contains(option))
|
if (userBlackList.contains(option))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
// TODO: Make it possible that the clang binary/driver ignores unknown options,
|
||||||
|
// as it is done for libclang/clangd (not checking for OPT_UNKNOWN).
|
||||||
|
if (toolChain == ProjectExplorer::Constants::MINGW_TOOLCHAIN_TYPEID) {
|
||||||
|
if (option == "-fkeep-inline-dllexport" || option == "-fno-keep-inline-dllexport")
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Ignore warning flags as these interfere with our user-configured diagnostics.
|
// Ignore warning flags as these interfere with our user-configured diagnostics.
|
||||||
// Note that once "-w" is provided, no warnings will be emitted, even if "-Wall" follows.
|
// Note that once "-w" is provided, no warnings will be emitted, even if "-Wall" follows.
|
||||||
if (m_useBuildSystemWarnings == UseBuildSystemWarnings::No
|
if (m_useBuildSystemWarnings == UseBuildSystemWarnings::No
|
||||||
@@ -755,7 +763,7 @@ void CompilerOptionsBuilder::evaluateCompilerFlags()
|
|||||||
|
|
||||||
// Check whether a language version is already used.
|
// Check whether a language version is already used.
|
||||||
QString theOption = option;
|
QString theOption = option;
|
||||||
if (theOption.startsWith("-std=")) {
|
if (theOption.startsWith("-std=") || theOption.startsWith("--std=")) {
|
||||||
m_compilerFlags.isLanguageVersionSpecified = true;
|
m_compilerFlags.isLanguageVersionSpecified = true;
|
||||||
theOption.replace("=c18", "=c17");
|
theOption.replace("=c18", "=c17");
|
||||||
theOption.replace("=gnu18", "=gnu17");
|
theOption.replace("=gnu18", "=gnu17");
|
||||||
@@ -772,7 +780,6 @@ void CompilerOptionsBuilder::evaluateCompilerFlags()
|
|||||||
m_compilerFlags.flags.append(theOption);
|
m_compilerFlags.flags.append(theOption);
|
||||||
}
|
}
|
||||||
|
|
||||||
const Core::Id &toolChain = m_projectPart.toolchainType;
|
|
||||||
if (!containsDriverMode
|
if (!containsDriverMode
|
||||||
&& (toolChain == ProjectExplorer::Constants::MSVC_TOOLCHAIN_TYPEID
|
&& (toolChain == ProjectExplorer::Constants::MSVC_TOOLCHAIN_TYPEID
|
||||||
|| toolChain == ProjectExplorer::Constants::CLANG_CL_TOOLCHAIN_TYPEID)) {
|
|| toolChain == ProjectExplorer::Constants::CLANG_CL_TOOLCHAIN_TYPEID)) {
|
||||||
|
@@ -1759,9 +1759,9 @@ void DebuggerPlugin::attachExternalApplication(RunControl *rc)
|
|||||||
ProcessHandle pid = rc->applicationProcessHandle();
|
ProcessHandle pid = rc->applicationProcessHandle();
|
||||||
auto runControl = new RunControl(ProjectExplorer::Constants::DEBUG_RUN_MODE);
|
auto runControl = new RunControl(ProjectExplorer::Constants::DEBUG_RUN_MODE);
|
||||||
runControl->setTarget(rc->target());
|
runControl->setTarget(rc->target());
|
||||||
|
runControl->setDisplayName(tr("Process %1").arg(pid.pid()));
|
||||||
auto debugger = new DebuggerRunTool(runControl);
|
auto debugger = new DebuggerRunTool(runControl);
|
||||||
debugger->setAttachPid(pid);
|
debugger->setAttachPid(pid);
|
||||||
debugger->setRunControlName(tr("Process %1").arg(pid.pid()));
|
|
||||||
debugger->setStartMode(AttachExternal);
|
debugger->setStartMode(AttachExternal);
|
||||||
debugger->setCloseMode(DetachAtClose);
|
debugger->setCloseMode(DetachAtClose);
|
||||||
debugger->startRunControl();
|
debugger->startRunControl();
|
||||||
|
@@ -605,7 +605,7 @@ BaseSettingsWidget::BaseSettingsWidget(const BaseSettings *settings, QWidget *pa
|
|||||||
mainLayout->addLayout(mimeLayout, row, 1);
|
mainLayout->addLayout(mimeLayout, row, 1);
|
||||||
m_filePattern->setPlaceholderText(tr("File pattern"));
|
m_filePattern->setPlaceholderText(tr("File pattern"));
|
||||||
mainLayout->addWidget(m_filePattern, ++row, 1);
|
mainLayout->addWidget(m_filePattern, ++row, 1);
|
||||||
mainLayout->addWidget(new QLabel(tr("Startup Behavior:")), ++row, 0);
|
mainLayout->addWidget(new QLabel(tr("Startup behavior:")), ++row, 0);
|
||||||
for (int behavior = 0; behavior < BaseSettings::LastSentinel ; ++behavior)
|
for (int behavior = 0; behavior < BaseSettings::LastSentinel ; ++behavior)
|
||||||
m_startupBehavior->addItem(startupBehaviorString(BaseSettings::StartBehavior(behavior)));
|
m_startupBehavior->addItem(startupBehaviorString(BaseSettings::StartBehavior(behavior)));
|
||||||
m_startupBehavior->setCurrentIndex(settings->m_startBehavior);
|
m_startupBehavior->setCurrentIndex(settings->m_startBehavior);
|
||||||
@@ -650,8 +650,8 @@ QString BaseSettingsWidget::name() const
|
|||||||
|
|
||||||
LanguageFilter BaseSettingsWidget::filter() const
|
LanguageFilter BaseSettingsWidget::filter() const
|
||||||
{
|
{
|
||||||
return {m_mimeTypes->text().split(filterSeparator),
|
return {m_mimeTypes->text().split(filterSeparator, QString::SkipEmptyParts),
|
||||||
m_filePattern->text().split(filterSeparator)};
|
m_filePattern->text().split(filterSeparator, QString::SkipEmptyParts)};
|
||||||
}
|
}
|
||||||
|
|
||||||
BaseSettings::StartBehavior BaseSettingsWidget::startupBehavior() const
|
BaseSettings::StartBehavior BaseSettingsWidget::startupBehavior() const
|
||||||
@@ -784,10 +784,10 @@ QString StdIOSettingsWidget::arguments() const
|
|||||||
|
|
||||||
bool LanguageFilter::isSupported(const Utils::FilePath &filePath, const QString &mimeType) const
|
bool LanguageFilter::isSupported(const Utils::FilePath &filePath, const QString &mimeType) const
|
||||||
{
|
{
|
||||||
if (mimeTypes.isEmpty() && filePattern.isEmpty())
|
|
||||||
return true;
|
|
||||||
if (mimeTypes.contains(mimeType))
|
if (mimeTypes.contains(mimeType))
|
||||||
return true;
|
return true;
|
||||||
|
if (filePattern.isEmpty() && filePath.isEmpty())
|
||||||
|
return mimeTypes.isEmpty();
|
||||||
auto regexps = Utils::transform(filePattern, [](const QString &pattern){
|
auto regexps = Utils::transform(filePattern, [](const QString &pattern){
|
||||||
return QRegExp(pattern, Utils::HostOsInfo::fileNameCaseSensitivity(), QRegExp::Wildcard);
|
return QRegExp(pattern, Utils::HostOsInfo::fileNameCaseSensitivity(), QRegExp::Wildcard);
|
||||||
});
|
});
|
||||||
|
@@ -157,6 +157,9 @@ PerfProfilerTool::PerfProfilerTool()
|
|||||||
tracePointsAction->setEnabled(m_startAction->isEnabled());
|
tracePointsAction->setEnabled(m_startAction->isEnabled());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
connect(ProjectExplorerPlugin::instance(), &ProjectExplorerPlugin::updateRunActions,
|
||||||
|
this, &PerfProfilerTool::updateRunActions);
|
||||||
|
|
||||||
m_recordButton = new QToolButton;
|
m_recordButton = new QToolButton;
|
||||||
m_clearButton = new QToolButton;
|
m_clearButton = new QToolButton;
|
||||||
m_filterButton = new QToolButton;
|
m_filterButton = new QToolButton;
|
||||||
@@ -341,9 +344,6 @@ void PerfProfilerTool::createViews()
|
|||||||
menu1->exec(m_flameGraphView->mapToGlobal(pos));
|
menu1->exec(m_flameGraphView->mapToGlobal(pos));
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(ProjectExplorerPlugin::instance(), &ProjectExplorerPlugin::updateRunActions,
|
|
||||||
this, &PerfProfilerTool::updateRunActions);
|
|
||||||
|
|
||||||
m_perspective.addToolBarAction(m_startAction);
|
m_perspective.addToolBarAction(m_startAction);
|
||||||
m_perspective.addToolBarAction(m_stopAction);
|
m_perspective.addToolBarAction(m_stopAction);
|
||||||
m_perspective.addToolBarWidget(m_recordButton);
|
m_perspective.addToolBarWidget(m_recordButton);
|
||||||
|
@@ -213,6 +213,7 @@ AppOutputPane::AppOutputPane() :
|
|||||||
|
|
||||||
connect(this, &Core::IOutputPane::zoomIn, this, &AppOutputPane::zoomIn);
|
connect(this, &Core::IOutputPane::zoomIn, this, &AppOutputPane::zoomIn);
|
||||||
connect(this, &Core::IOutputPane::zoomOut, this, &AppOutputPane::zoomOut);
|
connect(this, &Core::IOutputPane::zoomOut, this, &AppOutputPane::zoomOut);
|
||||||
|
connect(this, &IOutputPane::resetZoom, this, &AppOutputPane::resetZoom);
|
||||||
|
|
||||||
m_settingsButton->setToolTip(tr("Open Settings Page"));
|
m_settingsButton->setToolTip(tr("Open Settings Page"));
|
||||||
m_settingsButton->setIcon(Utils::Icons::SETTINGS_TOOLBAR.icon());
|
m_settingsButton->setIcon(Utils::Icons::SETTINGS_TOOLBAR.icon());
|
||||||
@@ -247,6 +248,7 @@ AppOutputPane::AppOutputPane() :
|
|||||||
setupFilterUi("AppOutputPane.Filter");
|
setupFilterUi("AppOutputPane.Filter");
|
||||||
setFilteringEnabled(false);
|
setFilteringEnabled(false);
|
||||||
setZoomButtonsEnabled(false);
|
setZoomButtonsEnabled(false);
|
||||||
|
setupContext("Core.AppOutputPane", m_mainWidget);
|
||||||
}
|
}
|
||||||
|
|
||||||
AppOutputPane::~AppOutputPane()
|
AppOutputPane::~AppOutputPane()
|
||||||
@@ -662,6 +664,12 @@ void AppOutputPane::zoomOut(int range)
|
|||||||
tab.window->zoomOut(range);
|
tab.window->zoomOut(range);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AppOutputPane::resetZoom()
|
||||||
|
{
|
||||||
|
for (const RunControlTab &tab : qAsConst(m_runControlTabs))
|
||||||
|
tab.window->resetZoom();
|
||||||
|
}
|
||||||
|
|
||||||
void AppOutputPane::enableButtons(const RunControl *rc)
|
void AppOutputPane::enableButtons(const RunControl *rc)
|
||||||
{
|
{
|
||||||
if (rc) {
|
if (rc) {
|
||||||
|
@@ -120,6 +120,7 @@ private:
|
|||||||
|
|
||||||
void zoomIn(int range);
|
void zoomIn(int range);
|
||||||
void zoomOut(int range);
|
void zoomOut(int range);
|
||||||
|
void resetZoom();
|
||||||
|
|
||||||
void enableButtons(const RunControl *rc);
|
void enableButtons(const RunControl *rc);
|
||||||
|
|
||||||
|
@@ -177,6 +177,7 @@ CompileOutputWindow::CompileOutputWindow(QAction *cancelBuildAction) :
|
|||||||
|
|
||||||
connect(this, &IOutputPane::zoomIn, m_outputWindow, &Core::OutputWindow::zoomIn);
|
connect(this, &IOutputPane::zoomIn, m_outputWindow, &Core::OutputWindow::zoomIn);
|
||||||
connect(this, &IOutputPane::zoomOut, m_outputWindow, &Core::OutputWindow::zoomOut);
|
connect(this, &IOutputPane::zoomOut, m_outputWindow, &Core::OutputWindow::zoomOut);
|
||||||
|
connect(this, &IOutputPane::resetZoom, m_outputWindow, &Core::OutputWindow::resetZoom);
|
||||||
connect(TextEditor::TextEditorSettings::instance(), &TextEditor::TextEditorSettings::fontSettingsChanged,
|
connect(TextEditor::TextEditorSettings::instance(), &TextEditor::TextEditorSettings::fontSettingsChanged,
|
||||||
this, updateFontSettings);
|
this, updateFontSettings);
|
||||||
connect(TextEditor::TextEditorSettings::instance(), &TextEditor::TextEditorSettings::behaviorSettingsChanged,
|
connect(TextEditor::TextEditorSettings::instance(), &TextEditor::TextEditorSettings::behaviorSettingsChanged,
|
||||||
@@ -194,6 +195,7 @@ CompileOutputWindow::CompileOutputWindow(QAction *cancelBuildAction) :
|
|||||||
|
|
||||||
m_handler = new ShowOutputTaskHandler(this);
|
m_handler = new ShowOutputTaskHandler(this);
|
||||||
ExtensionSystem::PluginManager::addObject(m_handler);
|
ExtensionSystem::PluginManager::addObject(m_handler);
|
||||||
|
setupContext(C_COMPILE_OUTPUT, m_outputWindow);
|
||||||
loadSettings();
|
loadSettings();
|
||||||
updateFromSettings();
|
updateFromSettings();
|
||||||
}
|
}
|
||||||
|
@@ -381,7 +381,7 @@ void EnvironmentWidget::amendPathList(const PathListModifier &modifier)
|
|||||||
{
|
{
|
||||||
const QString varName = d->m_model->indexToVariable(d->m_environmentView->currentIndex());
|
const QString varName = d->m_model->indexToVariable(d->m_environmentView->currentIndex());
|
||||||
const QString dir = QDir::toNativeSeparators(
|
const QString dir = QDir::toNativeSeparators(
|
||||||
QFileDialog::getExistingDirectory(this, tr("Choose a directory")));
|
QFileDialog::getExistingDirectory(this, tr("Choose Directory")));
|
||||||
if (dir.isEmpty())
|
if (dir.isEmpty())
|
||||||
return;
|
return;
|
||||||
QModelIndex index = d->m_model->variableToIndex(varName);
|
QModelIndex index = d->m_model->variableToIndex(varName);
|
||||||
|
@@ -92,7 +92,7 @@ class FilterKitAspectsModel : public TreeModel<TreeItem, FilterTreeItem>
|
|||||||
public:
|
public:
|
||||||
FilterKitAspectsModel(const Kit *kit, QObject *parent) : TreeModel(parent)
|
FilterKitAspectsModel(const Kit *kit, QObject *parent) : TreeModel(parent)
|
||||||
{
|
{
|
||||||
setHeader({tr("Setting"), tr("Visible")});
|
setHeader({FilterKitAspectsDialog::tr("Setting"), FilterKitAspectsDialog::tr("Visible")});
|
||||||
for (const KitAspect * const aspect : KitManager::kitAspects()) {
|
for (const KitAspect * const aspect : KitManager::kitAspects()) {
|
||||||
if (kit && !aspect->isApplicableToKit(kit))
|
if (kit && !aspect->isApplicableToKit(kit))
|
||||||
continue;
|
continue;
|
||||||
|
@@ -37,6 +37,7 @@ namespace Internal {
|
|||||||
|
|
||||||
class FilterKitAspectsDialog : public QDialog
|
class FilterKitAspectsDialog : public QDialog
|
||||||
{
|
{
|
||||||
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
FilterKitAspectsDialog(const Kit *kit, QWidget *parent);
|
FilterKitAspectsDialog(const Kit *kit, QWidget *parent);
|
||||||
QSet<Core::Id> irrelevantAspects() const;
|
QSet<Core::Id> irrelevantAspects() const;
|
||||||
|
@@ -63,10 +63,14 @@ ImportWidget::ImportWidget(QWidget *parent) :
|
|||||||
connect(importButton, &QAbstractButton::clicked, this, &ImportWidget::handleImportRequest);
|
connect(importButton, &QAbstractButton::clicked, this, &ImportWidget::handleImportRequest);
|
||||||
connect(m_pathChooser->lineEdit(), &QLineEdit::returnPressed, this, [this] {
|
connect(m_pathChooser->lineEdit(), &QLineEdit::returnPressed, this, [this] {
|
||||||
if (m_pathChooser->isValid()) {
|
if (m_pathChooser->isValid()) {
|
||||||
|
m_ownsReturnKey = true;
|
||||||
handleImportRequest();
|
handleImportRequest();
|
||||||
|
|
||||||
// The next return should trigger the "Configure" button.
|
// The next return should trigger the "Configure" button.
|
||||||
QTimer::singleShot(0, this, QOverload<>::of(&QWidget::setFocus));
|
QTimer::singleShot(0, this, [this] {
|
||||||
|
setFocus();
|
||||||
|
m_ownsReturnKey = false;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -79,9 +83,9 @@ void ImportWidget::setCurrentDirectory(const Utils::FilePath &dir)
|
|||||||
m_pathChooser->setFileName(dir);
|
m_pathChooser->setFileName(dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ImportWidget::lineEditHasFocus() const
|
bool ImportWidget::ownsReturnKey() const
|
||||||
{
|
{
|
||||||
return m_pathChooser->lineEdit()->hasFocus();
|
return m_ownsReturnKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImportWidget::handleImportRequest()
|
void ImportWidget::handleImportRequest()
|
||||||
|
@@ -44,7 +44,7 @@ public:
|
|||||||
|
|
||||||
void setCurrentDirectory(const Utils::FilePath &dir);
|
void setCurrentDirectory(const Utils::FilePath &dir);
|
||||||
|
|
||||||
bool lineEditHasFocus() const;
|
bool ownsReturnKey() const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void importFrom(const Utils::FilePath &dir);
|
void importFrom(const Utils::FilePath &dir);
|
||||||
@@ -53,6 +53,7 @@ private:
|
|||||||
void handleImportRequest();
|
void handleImportRequest();
|
||||||
|
|
||||||
Utils::PathChooser *m_pathChooser;
|
Utils::PathChooser *m_pathChooser;
|
||||||
|
bool m_ownsReturnKey = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
@@ -104,7 +104,7 @@ public:
|
|||||||
: QDialog(parent), m_view(new Utils::TreeView(this))
|
: QDialog(parent), m_view(new Utils::TreeView(this))
|
||||||
{
|
{
|
||||||
setWindowTitle(QCoreApplication::translate("ProjectExplorer::JsonWizard",
|
setWindowTitle(QCoreApplication::translate("ProjectExplorer::JsonWizard",
|
||||||
"Choose project file"));
|
"Choose Project File"));
|
||||||
const auto model = new ProjectFilesModel(candidates, this);
|
const auto model = new ProjectFilesModel(candidates, this);
|
||||||
m_view->setSelectionMode(Utils::TreeView::ExtendedSelection);
|
m_view->setSelectionMode(Utils::TreeView::ExtendedSelection);
|
||||||
m_view->setSelectionBehavior(Utils::TreeView::SelectRows);
|
m_view->setSelectionBehavior(Utils::TreeView::SelectRows);
|
||||||
@@ -121,7 +121,7 @@ public:
|
|||||||
const auto layout = new QVBoxLayout(this);
|
const auto layout = new QVBoxLayout(this);
|
||||||
layout->addWidget(new QLabel(QCoreApplication::translate("ProjectExplorer::JsonWizard",
|
layout->addWidget(new QLabel(QCoreApplication::translate("ProjectExplorer::JsonWizard",
|
||||||
"The project contains more than one project file. "
|
"The project contains more than one project file. "
|
||||||
"Please select the one you would like to use.")));
|
"Select the one you would like to use.")));
|
||||||
layout->addWidget(m_view);
|
layout->addWidget(m_view);
|
||||||
layout->addWidget(buttonBox);
|
layout->addWidget(buttonBox);
|
||||||
}
|
}
|
||||||
|
@@ -1298,6 +1298,7 @@ MsvcToolChainConfigWidget::MsvcToolChainConfigWidget(ToolChain *tc)
|
|||||||
m_mainLayout->removeRow(m_mainLayout->rowCount() - 1);
|
m_mainLayout->removeRow(m_mainLayout->rowCount() - 1);
|
||||||
|
|
||||||
QHBoxLayout *hLayout = new QHBoxLayout();
|
QHBoxLayout *hLayout = new QHBoxLayout();
|
||||||
|
m_varsBatPathCombo->setObjectName("varsBatCombo");
|
||||||
m_varsBatPathCombo->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
|
m_varsBatPathCombo->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
|
||||||
m_varsBatPathCombo->setEditable(true);
|
m_varsBatPathCombo->setEditable(true);
|
||||||
for (const MsvcToolChain *tmpTc : g_availableMsvcToolchains) {
|
for (const MsvcToolChain *tmpTc : g_availableMsvcToolchains) {
|
||||||
@@ -1442,6 +1443,7 @@ ClangClToolChainConfigWidget::ClangClToolChainConfigWidget(ToolChain *tc) :
|
|||||||
{
|
{
|
||||||
m_mainLayout->removeRow(m_mainLayout->rowCount() - 1);
|
m_mainLayout->removeRow(m_mainLayout->rowCount() - 1);
|
||||||
|
|
||||||
|
m_varsBatDisplayCombo->setObjectName("varsBatCombo");
|
||||||
m_varsBatDisplayCombo->setSizeAdjustPolicy(QComboBox::AdjustToContents);
|
m_varsBatDisplayCombo->setSizeAdjustPolicy(QComboBox::AdjustToContents);
|
||||||
m_mainLayout->addRow(tr("Initialization:"), m_varsBatDisplayCombo);
|
m_mainLayout->addRow(tr("Initialization:"), m_varsBatDisplayCombo);
|
||||||
|
|
||||||
|
@@ -71,14 +71,14 @@ ParseIssuesDialog::ParseIssuesDialog(QWidget *parent) : QDialog(parent), d(new P
|
|||||||
d->clearTasksCheckBox.setText(tr("Clear existing tasks"));
|
d->clearTasksCheckBox.setText(tr("Clear existing tasks"));
|
||||||
d->clearTasksCheckBox.setChecked(true);
|
d->clearTasksCheckBox.setChecked(true);
|
||||||
|
|
||||||
const auto loadFileButton = new QPushButton(tr("Load from file..."));
|
const auto loadFileButton = new QPushButton(tr("Load from File..."));
|
||||||
connect(loadFileButton, &QPushButton::clicked, this, [this] {
|
connect(loadFileButton, &QPushButton::clicked, this, [this] {
|
||||||
const QString filePath = QFileDialog::getOpenFileName(this, tr("Choose File"));
|
const QString filePath = QFileDialog::getOpenFileName(this, tr("Choose File"));
|
||||||
if (filePath.isEmpty())
|
if (filePath.isEmpty())
|
||||||
return;
|
return;
|
||||||
QFile file(filePath);
|
QFile file(filePath);
|
||||||
if (!file.open(QIODevice::ReadOnly)) {
|
if (!file.open(QIODevice::ReadOnly)) {
|
||||||
QMessageBox::critical(this, tr("Could not open file"),
|
QMessageBox::critical(this, tr("Could Not Open File"),
|
||||||
tr("Could not open file: \"%1\": %2")
|
tr("Could not open file: \"%1\": %2")
|
||||||
.arg(filePath, file.errorString()));
|
.arg(filePath, file.errorString()));
|
||||||
return;
|
return;
|
||||||
@@ -116,7 +116,7 @@ ParseIssuesDialog::ParseIssuesDialog(QWidget *parent) : QDialog(parent), d(new P
|
|||||||
// TODO: Only very few parsers are available from a Kit (basically just the Toolchain one).
|
// TODO: Only very few parsers are available from a Kit (basically just the Toolchain one).
|
||||||
// If we introduced factories for IOutputParsers, we could offer the user
|
// If we introduced factories for IOutputParsers, we could offer the user
|
||||||
// to combine arbitrary parsers here.
|
// to combine arbitrary parsers here.
|
||||||
const auto parserGroupBox = new QGroupBox(tr("Parsing options"));
|
const auto parserGroupBox = new QGroupBox(tr("Parsing Options"));
|
||||||
layout->addWidget(parserGroupBox);
|
layout->addWidget(parserGroupBox);
|
||||||
const auto parserLayout = new QVBoxLayout(parserGroupBox);
|
const auto parserLayout = new QVBoxLayout(parserGroupBox);
|
||||||
const auto kitChooserWidget = new QWidget;
|
const auto kitChooserWidget = new QWidget;
|
||||||
@@ -153,7 +153,7 @@ void ParseIssuesDialog::accept()
|
|||||||
{
|
{
|
||||||
std::unique_ptr<IOutputParser> parser(d->kitChooser.currentKit()->createOutputParser());
|
std::unique_ptr<IOutputParser> parser(d->kitChooser.currentKit()->createOutputParser());
|
||||||
if (!parser) {
|
if (!parser) {
|
||||||
QMessageBox::critical(this, tr("Cannot parse"), tr("Cannot parse: The chosen kit does "
|
QMessageBox::critical(this, tr("Cannot Parse"), tr("Cannot parse: The chosen kit does "
|
||||||
"not provide an output parser."));
|
"not provide an output parser."));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@@ -667,7 +667,7 @@ void Project::changeRootProjectDirectory()
|
|||||||
{
|
{
|
||||||
Utils::FilePath rootPath = Utils::FilePath::fromString(
|
Utils::FilePath rootPath = Utils::FilePath::fromString(
|
||||||
QFileDialog::getExistingDirectory(Core::ICore::dialogParent(),
|
QFileDialog::getExistingDirectory(Core::ICore::dialogParent(),
|
||||||
tr("Select The Root Directory"),
|
tr("Select the Root Directory"),
|
||||||
rootProjectDirectory().toString(),
|
rootProjectDirectory().toString(),
|
||||||
QFileDialog::ShowDirsOnly
|
QFileDialog::ShowDirsOnly
|
||||||
| QFileDialog::DontResolveSymlinks));
|
| QFileDialog::DontResolveSymlinks));
|
||||||
@@ -679,7 +679,7 @@ void Project::changeRootProjectDirectory()
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Returns the common root directory that contains all files which belongs to a project.
|
Returns the common root directory that contains all files which belong to a project.
|
||||||
*/
|
*/
|
||||||
Utils::FilePath Project::rootProjectDirectory() const
|
Utils::FilePath Project::rootProjectDirectory() const
|
||||||
{
|
{
|
||||||
|
@@ -1780,7 +1780,7 @@ void ProjectExplorerPlugin::unloadProject(Project *project)
|
|||||||
|
|
||||||
void ProjectExplorerPluginPrivate::closeAllProjects()
|
void ProjectExplorerPluginPrivate::closeAllProjects()
|
||||||
{
|
{
|
||||||
if (!EditorManager::closeAllEditors())
|
if (!EditorManager::closeAllDocuments())
|
||||||
return; // Action has been cancelled
|
return; // Action has been cancelled
|
||||||
|
|
||||||
SessionManager::closeAllProjects();
|
SessionManager::closeAllProjects();
|
||||||
@@ -1935,15 +1935,15 @@ void ProjectExplorerPluginPrivate::setStartupProject(Project *project)
|
|||||||
bool ProjectExplorerPluginPrivate::closeAllFilesInProject(const Project *project)
|
bool ProjectExplorerPluginPrivate::closeAllFilesInProject(const Project *project)
|
||||||
{
|
{
|
||||||
QTC_ASSERT(project, return false);
|
QTC_ASSERT(project, return false);
|
||||||
QList<IDocument *> openFiles = DocumentModel::openedDocuments();
|
QList<DocumentModel::Entry *> openFiles = DocumentModel::entries();
|
||||||
Utils::erase(openFiles, [project](const IDocument *doc) {
|
Utils::erase(openFiles, [project](const DocumentModel::Entry *entry) {
|
||||||
return !project->isKnownFile(doc->filePath());
|
return entry->pinned || !project->isKnownFile(entry->fileName());
|
||||||
});
|
});
|
||||||
for (const Project * const otherProject : SessionManager::projects()) {
|
for (const Project * const otherProject : SessionManager::projects()) {
|
||||||
if (otherProject == project)
|
if (otherProject == project)
|
||||||
continue;
|
continue;
|
||||||
Utils::erase(openFiles, [otherProject](const IDocument *doc) {
|
Utils::erase(openFiles, [otherProject](const DocumentModel::Entry *entry) {
|
||||||
return otherProject->isKnownFile(doc->filePath());
|
return otherProject->isKnownFile(entry->fileName());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return EditorManager::closeDocuments(openFiles);
|
return EditorManager::closeDocuments(openFiles);
|
||||||
@@ -3470,7 +3470,7 @@ void ProjectExplorerPluginPrivate::addExistingProjects()
|
|||||||
QTC_ASSERT(projectNode, return);
|
QTC_ASSERT(projectNode, return);
|
||||||
const QString dir = directoryFor(currentNode);
|
const QString dir = directoryFor(currentNode);
|
||||||
QStringList subProjectFilePaths = QFileDialog::getOpenFileNames(
|
QStringList subProjectFilePaths = QFileDialog::getOpenFileNames(
|
||||||
ICore::mainWindow(), tr("Please choose a project file"), dir,
|
ICore::mainWindow(), tr("Choose Project File"), dir,
|
||||||
projectNode->subProjectFileNamePatterns().join(";;"));
|
projectNode->subProjectFileNamePatterns().join(";;"));
|
||||||
if (!ProjectTree::hasNode(projectNode))
|
if (!ProjectTree::hasNode(projectNode))
|
||||||
return;
|
return;
|
||||||
|
@@ -457,7 +457,7 @@ public:
|
|||||||
: m_buttonBox(new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel)),
|
: m_buttonBox(new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel)),
|
||||||
m_buttonGroup(new QButtonGroup(this))
|
m_buttonGroup(new QButtonGroup(this))
|
||||||
{
|
{
|
||||||
setWindowTitle(tr("Please choose a drop action"));
|
setWindowTitle(tr("Choose Drop Action"));
|
||||||
const bool offerFileIo = !defaultTargetDir.isEmpty();
|
const bool offerFileIo = !defaultTargetDir.isEmpty();
|
||||||
auto * const layout = new QVBoxLayout(this);
|
auto * const layout = new QVBoxLayout(this);
|
||||||
layout->addWidget(new QLabel(tr("You just dragged some files from one project node to "
|
layout->addWidget(new QLabel(tr("You just dragged some files from one project node to "
|
||||||
@@ -469,8 +469,8 @@ public:
|
|||||||
m_buttonGroup->addButton(moveButton, int(DropAction::Move));
|
m_buttonGroup->addButton(moveButton, int(DropAction::Move));
|
||||||
layout->addWidget(moveButton);
|
layout->addWidget(moveButton);
|
||||||
if (offerFileIo) {
|
if (offerFileIo) {
|
||||||
copyButton->setText(tr("Copy only the file references"));
|
copyButton->setText(tr("Copy Only File References"));
|
||||||
moveButton->setText(tr("Move only the file references"));
|
moveButton->setText(tr("Move Only File References"));
|
||||||
auto * const copyWithFilesButton
|
auto * const copyWithFilesButton
|
||||||
= new QRadioButton(tr("Copy file references and files"), this);
|
= new QRadioButton(tr("Copy file references and files"), this);
|
||||||
m_buttonGroup->addButton(copyWithFilesButton, int(DropAction::CopyWithFiles));
|
m_buttonGroup->addButton(copyWithFilesButton, int(DropAction::CopyWithFiles));
|
||||||
@@ -506,8 +506,8 @@ public:
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
copyButton->setText(tr("Copy the file references"));
|
copyButton->setText(tr("Copy File References"));
|
||||||
moveButton->setText(tr("Move the file references"));
|
moveButton->setText(tr("Move File References"));
|
||||||
moveButton->setChecked(true);
|
moveButton->setChecked(true);
|
||||||
}
|
}
|
||||||
connect(m_buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
|
connect(m_buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
|
||||||
|
@@ -332,7 +332,7 @@ void TargetSetupPage::setProjectImporter(ProjectImporter *importer)
|
|||||||
|
|
||||||
bool TargetSetupPage::importLineEditHasFocus() const
|
bool TargetSetupPage::importLineEditHasFocus() const
|
||||||
{
|
{
|
||||||
return m_importWidget->lineEditHasFocus();
|
return m_importWidget->ownsReturnKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TargetSetupPage::setNoteText(const QString &text)
|
void TargetSetupPage::setNoteText(const QString &text)
|
||||||
|
@@ -164,7 +164,7 @@ KitAspect::ItemList QmakeKitAspect::toUserOutput(const Kit *k) const
|
|||||||
|
|
||||||
void QmakeKitAspect::addToMacroExpander(Kit *kit, MacroExpander *expander) const
|
void QmakeKitAspect::addToMacroExpander(Kit *kit, MacroExpander *expander) const
|
||||||
{
|
{
|
||||||
expander->registerVariable("Qmake:mkspec", tr("Mkspec configured for qmake by the Kit."),
|
expander->registerVariable("Qmake:mkspec", tr("Mkspec configured for qmake by the kit."),
|
||||||
[kit]() -> QString {
|
[kit]() -> QString {
|
||||||
return QDir::toNativeSeparators(mkspec(kit));
|
return QDir::toNativeSeparators(mkspec(kit));
|
||||||
});
|
});
|
||||||
|
@@ -103,7 +103,7 @@ public:
|
|||||||
m_warnAgainstUnalignedBuildDirCheckbox.setText(tr("Warn if a project's source and "
|
m_warnAgainstUnalignedBuildDirCheckbox.setText(tr("Warn if a project's source and "
|
||||||
"build directories are not at the same level"));
|
"build directories are not at the same level"));
|
||||||
m_warnAgainstUnalignedBuildDirCheckbox.setToolTip(tr("Qmake has subtle bugs that "
|
m_warnAgainstUnalignedBuildDirCheckbox.setToolTip(tr("Qmake has subtle bugs that "
|
||||||
"can trigger if source and build directory are not at the same level."));
|
"can be triggered if source and build directory are not at the same level."));
|
||||||
m_warnAgainstUnalignedBuildDirCheckbox.setChecked(
|
m_warnAgainstUnalignedBuildDirCheckbox.setChecked(
|
||||||
QmakeSettings::warnAgainstUnalignedBuildDir());
|
QmakeSettings::warnAgainstUnalignedBuildDir());
|
||||||
m_alwaysRunQmakeCheckbox.setText(tr("Run qmake on every build"));
|
m_alwaysRunQmakeCheckbox.setText(tr("Run qmake on every build"));
|
||||||
|
@@ -165,6 +165,7 @@ const int priorityGenericToolBar = 50;
|
|||||||
const int priorityLast = 60;
|
const int priorityLast = 60;
|
||||||
|
|
||||||
const char addImagesDisplayString[] = QT_TRANSLATE_NOOP("QmlDesignerAddResources", "Image Files");
|
const char addImagesDisplayString[] = QT_TRANSLATE_NOOP("QmlDesignerAddResources", "Image Files");
|
||||||
|
const char addFontsDisplayString[] = QT_TRANSLATE_NOOP("QmlDesignerAddResources", "Font Files");
|
||||||
|
|
||||||
} //ComponentCoreConstants
|
} //ComponentCoreConstants
|
||||||
|
|
||||||
|
@@ -1026,6 +1026,13 @@ void DesignerActionManager::createDefaultAddResourceHandler()
|
|||||||
registerAddResourceHandler(AddResourceHandler(ComponentCoreConstants::addImagesDisplayString,
|
registerAddResourceHandler(AddResourceHandler(ComponentCoreConstants::addImagesDisplayString,
|
||||||
"*.svg",
|
"*.svg",
|
||||||
ModelNodeOperations::addImageToProject));
|
ModelNodeOperations::addImageToProject));
|
||||||
|
|
||||||
|
registerAddResourceHandler(AddResourceHandler(ComponentCoreConstants::addFontsDisplayString,
|
||||||
|
"*.ttf",
|
||||||
|
ModelNodeOperations::addFontToProject));
|
||||||
|
registerAddResourceHandler(AddResourceHandler(ComponentCoreConstants::addFontsDisplayString,
|
||||||
|
"*.otf",
|
||||||
|
ModelNodeOperations::addFontToProject));
|
||||||
}
|
}
|
||||||
|
|
||||||
void DesignerActionManager::addDesignerAction(ActionInterface *newAction)
|
void DesignerActionManager::addDesignerAction(ActionInterface *newAction)
|
||||||
|
@@ -966,6 +966,38 @@ void addTabBarToStackedContainer(const SelectionContext &selectionContext)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool addFontToProject(const QStringList &fileNames, const QString &defaultDirectory)
|
||||||
|
{
|
||||||
|
QString directory = AddImagesDialog::getDirectory(fileNames, defaultDirectory);
|
||||||
|
|
||||||
|
if (directory.isEmpty())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
bool allSuccessful = true;
|
||||||
|
for (const QString &fileName : fileNames) {
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
allSuccessful = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return allSuccessful;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool addImageToProject(const QStringList &fileNames, const QString &defaultDirectory)
|
bool addImageToProject(const QStringList &fileNames, const QString &defaultDirectory)
|
||||||
{
|
{
|
||||||
QString directory = AddImagesDialog::getDirectory(fileNames, defaultDirectory);
|
QString directory = AddImagesDialog::getDirectory(fileNames, defaultDirectory);
|
||||||
|
@@ -73,6 +73,7 @@ void increaseIndexOfStackedContainer(const SelectionContext &selectionContext);
|
|||||||
void decreaseIndexOfStackedContainer(const SelectionContext &selectionContext);
|
void decreaseIndexOfStackedContainer(const SelectionContext &selectionContext);
|
||||||
void addTabBarToStackedContainer(const SelectionContext &selectionContext);
|
void addTabBarToStackedContainer(const SelectionContext &selectionContext);
|
||||||
bool addImageToProject(const QStringList &fileNames, const QString &directory);
|
bool addImageToProject(const QStringList &fileNames, const QString &directory);
|
||||||
|
bool addFontToProject(const QStringList &fileNames, const QString &directory);
|
||||||
|
|
||||||
} // namespace ModelNodeOperationso
|
} // namespace ModelNodeOperationso
|
||||||
} //QmlDesigner
|
} //QmlDesigner
|
||||||
|
@@ -27,6 +27,7 @@
|
|||||||
|
|
||||||
#include <qmlitemnode.h>
|
#include <qmlitemnode.h>
|
||||||
|
|
||||||
|
#include <QDir>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
|
@@ -256,6 +256,11 @@ QList<DeployableFile> QnxDeployQtLibrariesDialog::gatherFiles(
|
|||||||
if (dirPath.isEmpty())
|
if (dirPath.isEmpty())
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
|
static const QStringList unusedDirs = {"include", "mkspecs", "cmake", "pkgconfig"};
|
||||||
|
const QString dp = dirPath.endsWith('/') ? dirPath.left(dirPath.size() - 1) : dirPath;
|
||||||
|
if (unusedDirs.contains(dp))
|
||||||
|
return result;
|
||||||
|
|
||||||
QDir dir(dirPath);
|
QDir dir(dirPath);
|
||||||
QFileInfoList list = dir.entryInfoList(nameFilters,
|
QFileInfoList list = dir.entryInfoList(nameFilters,
|
||||||
QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot);
|
QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot);
|
||||||
@@ -265,6 +270,10 @@ QList<DeployableFile> QnxDeployQtLibrariesDialog::gatherFiles(
|
|||||||
result.append(gatherFiles(fileInfo.absoluteFilePath(), baseDirPath.isEmpty() ?
|
result.append(gatherFiles(fileInfo.absoluteFilePath(), baseDirPath.isEmpty() ?
|
||||||
dirPath : baseDirPath));
|
dirPath : baseDirPath));
|
||||||
} else {
|
} else {
|
||||||
|
static const QStringList unusedSuffixes = {"cmake", "la", "prl", "a", "pc"};
|
||||||
|
if (unusedSuffixes.contains(fileInfo.suffix()))
|
||||||
|
continue;
|
||||||
|
|
||||||
QString remoteDir;
|
QString remoteDir;
|
||||||
if (baseDirPath.isEmpty()) {
|
if (baseDirPath.isEmpty()) {
|
||||||
remoteDir = fullRemoteDirectory() + QLatin1Char('/') +
|
remoteDir = fullRemoteDirectory() + QLatin1Char('/') +
|
||||||
|
@@ -118,13 +118,13 @@ bool MakeInstallStep::init()
|
|||||||
}
|
}
|
||||||
QDir rootDir(rootDirPath);
|
QDir rootDir(rootDirPath);
|
||||||
if (cleanInstallRoot() && !rootDir.removeRecursively()) {
|
if (cleanInstallRoot() && !rootDir.removeRecursively()) {
|
||||||
emit addTask(Task(Task::Error, tr("The install root '%1' could not be cleaned.")
|
emit addTask(Task(Task::Error, tr("The install root \"%1\" could not be cleaned.")
|
||||||
.arg(installRoot().toUserOutput()),
|
.arg(installRoot().toUserOutput()),
|
||||||
FilePath(), -1, Constants::TASK_CATEGORY_BUILDSYSTEM));
|
FilePath(), -1, Constants::TASK_CATEGORY_BUILDSYSTEM));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!rootDir.exists() && !QDir::root().mkpath(rootDirPath)) {
|
if (!rootDir.exists() && !QDir::root().mkpath(rootDirPath)) {
|
||||||
emit addTask(Task(Task::Error, tr("The install root '%1' could not be created.")
|
emit addTask(Task(Task::Error, tr("The install root \"%1\" could not be created.")
|
||||||
.arg(installRoot().toUserOutput()),
|
.arg(installRoot().toUserOutput()),
|
||||||
FilePath(), -1, Constants::TASK_CATEGORY_BUILDSYSTEM));
|
FilePath(), -1, Constants::TASK_CATEGORY_BUILDSYSTEM));
|
||||||
return false;
|
return false;
|
||||||
|
@@ -33,6 +33,7 @@
|
|||||||
#include <coreplugin/icore.h>
|
#include <coreplugin/icore.h>
|
||||||
#include <coreplugin/messagemanager.h>
|
#include <coreplugin/messagemanager.h>
|
||||||
#include <utils/mimetypes/mimedatabase.h>
|
#include <utils/mimetypes/mimedatabase.h>
|
||||||
|
#include <utils/qtcassert.h>
|
||||||
|
|
||||||
#include <DefinitionDownloader>
|
#include <DefinitionDownloader>
|
||||||
#include <Format>
|
#include <Format>
|
||||||
@@ -119,6 +120,8 @@ Highlighter::Definition Highlighter::definitionForDocument(const TextDocument *d
|
|||||||
|
|
||||||
Highlighter::Definition Highlighter::definitionForMimeType(const QString &mimeType)
|
Highlighter::Definition Highlighter::definitionForMimeType(const QString &mimeType)
|
||||||
{
|
{
|
||||||
|
if (mimeType.isEmpty())
|
||||||
|
return {};
|
||||||
const Definitions definitions = definitionsForMimeType(mimeType);
|
const Definitions definitions = definitionsForMimeType(mimeType);
|
||||||
if (definitions.size() == 1)
|
if (definitions.size() == 1)
|
||||||
return definitions.first();
|
return definitions.first();
|
||||||
@@ -140,13 +143,23 @@ Highlighter::Definition Highlighter::definitionForName(const QString &name)
|
|||||||
|
|
||||||
Highlighter::Definitions Highlighter::definitionsForDocument(const TextDocument *document)
|
Highlighter::Definitions Highlighter::definitionsForDocument(const TextDocument *document)
|
||||||
{
|
{
|
||||||
const Utils::MimeType mimeType = Utils::mimeTypeForName(document->mimeType());
|
QTC_ASSERT(document, return {});
|
||||||
Definitions definitions;
|
const Utils::MimeType &mimeType = Utils::mimeTypeForName(document->mimeType());
|
||||||
if (mimeType.isValid())
|
if (mimeType.isValid()) {
|
||||||
definitions = Highlighter::definitionsForMimeType(mimeType.name());
|
if (mimeType.name() == "text/plain") {
|
||||||
if (definitions.isEmpty())
|
// text/plain is the base mime type for all text types so ignore it and try matching the
|
||||||
definitions = Highlighter::definitionsForFileName(document->filePath());
|
// file name against the pattern and only if no definition can be found for the
|
||||||
return definitions;
|
// file name try matching the mime type
|
||||||
|
const Definitions &fileNameDefinitions = definitionsForFileName(document->filePath());
|
||||||
|
if (!fileNameDefinitions.isEmpty())
|
||||||
|
return fileNameDefinitions;
|
||||||
|
return definitionsForMimeType(mimeType.name());
|
||||||
|
}
|
||||||
|
const Definitions &mimeTypeDefinitions = definitionsForMimeType(mimeType.name());
|
||||||
|
if (!mimeTypeDefinitions.isEmpty())
|
||||||
|
return mimeTypeDefinitions;
|
||||||
|
}
|
||||||
|
return definitionsForFileName(document->filePath());
|
||||||
}
|
}
|
||||||
|
|
||||||
static Highlighter::Definition definitionForSetting(const QString &settingsKey,
|
static Highlighter::Definition definitionForSetting(const QString &settingsKey,
|
||||||
@@ -193,6 +206,7 @@ Highlighter::Definitions Highlighter::definitionsForFileName(const Utils::FilePa
|
|||||||
void Highlighter::rememberDefintionForDocument(const Highlighter::Definition &definition,
|
void Highlighter::rememberDefintionForDocument(const Highlighter::Definition &definition,
|
||||||
const TextDocument *document)
|
const TextDocument *document)
|
||||||
{
|
{
|
||||||
|
QTC_ASSERT(document, return );
|
||||||
if (!definition.isValid())
|
if (!definition.isValid())
|
||||||
return;
|
return;
|
||||||
const QString &mimeType = document->mimeType();
|
const QString &mimeType = document->mimeType();
|
||||||
|
@@ -630,7 +630,7 @@ MemcheckToolPrivate::MemcheckToolPrivate()
|
|||||||
});
|
});
|
||||||
|
|
||||||
action = new QAction(this);
|
action = new QAction(this);
|
||||||
action->setText(tr("Valgrind Memory Analyzer with GDB"));
|
action->setText(MemcheckTool::tr("Valgrind Memory Analyzer with GDB"));
|
||||||
action->setToolTip(MemcheckTool::tr("Valgrind Analyze Memory with GDB uses the "
|
action->setToolTip(MemcheckTool::tr("Valgrind Analyze Memory with GDB uses the "
|
||||||
"Memcheck tool to find memory leaks.\nWhen a problem is detected, "
|
"Memcheck tool to find memory leaks.\nWhen a problem is detected, "
|
||||||
"the application is interrupted and can be debugged."));
|
"the application is interrupted and can be debugged."));
|
||||||
@@ -650,7 +650,7 @@ MemcheckToolPrivate::MemcheckToolPrivate()
|
|||||||
} else {
|
} else {
|
||||||
action = new QAction(MemcheckTool::tr("Heob"), this);
|
action = new QAction(MemcheckTool::tr("Heob"), this);
|
||||||
Core::Command *cmd = Core::ActionManager::registerAction(action, "Memcheck.Local");
|
Core::Command *cmd = Core::ActionManager::registerAction(action, "Memcheck.Local");
|
||||||
cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+Alt+H")));
|
cmd->setDefaultKeySequence(QKeySequence(MemcheckTool::tr("Ctrl+Alt+H")));
|
||||||
connect(action, &QAction::triggered, this, &MemcheckToolPrivate::heobAction);
|
connect(action, &QAction::triggered, this, &MemcheckToolPrivate::heobAction);
|
||||||
menu->addAction(cmd, Debugger::Constants::G_ANALYZER_TOOLS);
|
menu->addAction(cmd, Debugger::Constants::G_ANALYZER_TOOLS);
|
||||||
connect(m_startAction, &QAction::changed, action, [action, this] {
|
connect(m_startAction, &QAction::changed, action, [action, this] {
|
||||||
@@ -659,7 +659,7 @@ MemcheckToolPrivate::MemcheckToolPrivate()
|
|||||||
}
|
}
|
||||||
|
|
||||||
action = new QAction(this);
|
action = new QAction(this);
|
||||||
action->setText(tr("Valgrind Memory Analyzer (External Application)"));
|
action->setText(MemcheckTool::tr("Valgrind Memory Analyzer (External Application)"));
|
||||||
action->setToolTip(toolTip);
|
action->setToolTip(toolTip);
|
||||||
menu->addAction(ActionManager::registerAction(action, "Memcheck.Remote"),
|
menu->addAction(ActionManager::registerAction(action, "Memcheck.Remote"),
|
||||||
Debugger::Constants::G_ANALYZER_REMOTE_TOOLS);
|
Debugger::Constants::G_ANALYZER_REMOTE_TOOLS);
|
||||||
@@ -724,7 +724,7 @@ void MemcheckToolPrivate::heobAction()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!hasLocalRc) {
|
if (!hasLocalRc) {
|
||||||
const QString msg = tr("Heob: No local run configuration available.");
|
const QString msg = MemcheckTool::tr("Heob: No local run configuration available.");
|
||||||
TaskHub::addTask(Task::Error, msg, Debugger::Constants::ANALYZERTASK_ID);
|
TaskHub::addTask(Task::Error, msg, Debugger::Constants::ANALYZERTASK_ID);
|
||||||
TaskHub::requestPopup();
|
TaskHub::requestPopup();
|
||||||
return;
|
return;
|
||||||
@@ -733,7 +733,7 @@ void MemcheckToolPrivate::heobAction()
|
|||||||
|| abi.os() != Abi::WindowsOS
|
|| abi.os() != Abi::WindowsOS
|
||||||
|| abi.binaryFormat() != Abi::PEFormat
|
|| abi.binaryFormat() != Abi::PEFormat
|
||||||
|| (abi.wordWidth() != 32 && abi.wordWidth() != 64)) {
|
|| (abi.wordWidth() != 32 && abi.wordWidth() != 64)) {
|
||||||
const QString msg = tr("Heob: No toolchain available.");
|
const QString msg = MemcheckTool::tr("Heob: No toolchain available.");
|
||||||
TaskHub::addTask(Task::Error, msg, Debugger::Constants::ANALYZERTASK_ID);
|
TaskHub::addTask(Task::Error, msg, Debugger::Constants::ANALYZERTASK_ID);
|
||||||
TaskHub::requestPopup();
|
TaskHub::requestPopup();
|
||||||
return;
|
return;
|
||||||
@@ -746,7 +746,7 @@ void MemcheckToolPrivate::heobAction()
|
|||||||
|
|
||||||
// target executable
|
// target executable
|
||||||
if (executable.isEmpty()) {
|
if (executable.isEmpty()) {
|
||||||
const QString msg = tr("Heob: No executable set.");
|
const QString msg = MemcheckTool::tr("Heob: No executable set.");
|
||||||
TaskHub::addTask(Task::Error, msg, Debugger::Constants::ANALYZERTASK_ID);
|
TaskHub::addTask(Task::Error, msg, Debugger::Constants::ANALYZERTASK_ID);
|
||||||
TaskHub::requestPopup();
|
TaskHub::requestPopup();
|
||||||
return;
|
return;
|
||||||
@@ -754,7 +754,7 @@ void MemcheckToolPrivate::heobAction()
|
|||||||
if (!QFile::exists(executable))
|
if (!QFile::exists(executable))
|
||||||
executable = Utils::HostOsInfo::withExecutableSuffix(executable);
|
executable = Utils::HostOsInfo::withExecutableSuffix(executable);
|
||||||
if (!QFile::exists(executable)) {
|
if (!QFile::exists(executable)) {
|
||||||
const QString msg = tr("Heob: Cannot find %1.").arg(executable);
|
const QString msg = MemcheckTool::tr("Heob: Cannot find %1.").arg(executable);
|
||||||
TaskHub::addTask(Task::Error, msg, Debugger::Constants::ANALYZERTASK_ID);
|
TaskHub::addTask(Task::Error, msg, Debugger::Constants::ANALYZERTASK_ID);
|
||||||
TaskHub::requestPopup();
|
TaskHub::requestPopup();
|
||||||
return;
|
return;
|
||||||
@@ -775,8 +775,10 @@ void MemcheckToolPrivate::heobAction()
|
|||||||
const QString heob = QString("heob%1.exe").arg(abi.wordWidth());
|
const QString heob = QString("heob%1.exe").arg(abi.wordWidth());
|
||||||
const QString heobPath = dialog.path() + '/' + heob;
|
const QString heobPath = dialog.path() + '/' + heob;
|
||||||
if (!QFile::exists(heobPath)) {
|
if (!QFile::exists(heobPath)) {
|
||||||
QMessageBox::critical(Core::ICore::mainWindow(), tr("Heob"),
|
QMessageBox::critical(
|
||||||
tr("The %1 executables must be in the appropriate location.")
|
Core::ICore::mainWindow(),
|
||||||
|
MemcheckTool::tr("Heob"),
|
||||||
|
MemcheckTool::tr("The %1 executables must be in the appropriate location.")
|
||||||
.arg("<a href=\"https://github.com/ssbssa/heob/releases\">Heob</a>"));
|
.arg("<a href=\"https://github.com/ssbssa/heob/releases\">Heob</a>"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -787,12 +789,18 @@ void MemcheckToolPrivate::heobAction()
|
|||||||
const QString dwarfstackPath = dialog.path() + '/' + dwarfstack;
|
const QString dwarfstackPath = dialog.path() + '/' + dwarfstack;
|
||||||
if (!QFile::exists(dwarfstackPath)
|
if (!QFile::exists(dwarfstackPath)
|
||||||
&& CheckableMessageBox::doNotShowAgainInformation(
|
&& CheckableMessageBox::doNotShowAgainInformation(
|
||||||
Core::ICore::mainWindow(), tr("Heob"),
|
Core::ICore::mainWindow(),
|
||||||
tr("Heob used with MinGW projects needs the %1 DLLs for proper stacktrace resolution.")
|
MemcheckTool::tr("Heob"),
|
||||||
.arg("<a href=\"https://github.com/ssbssa/dwarfstack/releases\">Dwarfstack</a>"),
|
MemcheckTool::tr("Heob used with MinGW projects needs the %1 DLLs for proper "
|
||||||
ICore::settings(), "HeobDwarfstackInfo",
|
"stacktrace resolution.")
|
||||||
|
.arg(
|
||||||
|
"<a "
|
||||||
|
"href=\"https://github.com/ssbssa/dwarfstack/releases\">Dwarfstack</a>"),
|
||||||
|
ICore::settings(),
|
||||||
|
"HeobDwarfstackInfo",
|
||||||
QDialogButtonBox::Ok | QDialogButtonBox::Cancel,
|
QDialogButtonBox::Ok | QDialogButtonBox::Cancel,
|
||||||
QDialogButtonBox::Ok) != QDialogButtonBox::Ok)
|
QDialogButtonBox::Ok)
|
||||||
|
!= QDialogButtonBox::Ok)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -837,7 +845,9 @@ void MemcheckToolPrivate::heobAction()
|
|||||||
CREATE_UNICODE_ENVIRONMENT | CREATE_SUSPENDED | CREATE_NEW_CONSOLE, envPtr,
|
CREATE_UNICODE_ENVIRONMENT | CREATE_SUSPENDED | CREATE_NEW_CONSOLE, envPtr,
|
||||||
reinterpret_cast<LPCWSTR>(workingDirectory.utf16()), &si, &pi)) {
|
reinterpret_cast<LPCWSTR>(workingDirectory.utf16()), &si, &pi)) {
|
||||||
DWORD e = GetLastError();
|
DWORD e = GetLastError();
|
||||||
const QString msg = tr("Heob: Cannot create %1 process (%2).").arg(heob).arg(qt_error_string(e));
|
const QString msg = MemcheckTool::tr("Heob: Cannot create %1 process (%2).")
|
||||||
|
.arg(heob)
|
||||||
|
.arg(qt_error_string(e));
|
||||||
TaskHub::addTask(Task::Error, msg, Debugger::Constants::ANALYZERTASK_ID);
|
TaskHub::addTask(Task::Error, msg, Debugger::Constants::ANALYZERTASK_ID);
|
||||||
TaskHub::requestPopup();
|
TaskHub::requestPopup();
|
||||||
return;
|
return;
|
||||||
|
@@ -239,7 +239,7 @@ void OutputWindowPlainTextEdit::appendLinesWithStyle(const QString &s,
|
|||||||
setFormat(style);
|
setFormat(style);
|
||||||
|
|
||||||
if (style == VcsOutputWindow::Command) {
|
if (style == VcsOutputWindow::Command) {
|
||||||
const QString timeStamp = QTime::currentTime().toString("\nHH:mm ");
|
const QString timeStamp = QTime::currentTime().toString("\nHH:mm:ss ");
|
||||||
appendLines(timeStamp + s, repository);
|
appendLines(timeStamp + s, repository);
|
||||||
} else {
|
} else {
|
||||||
appendLines(s, repository);
|
appendLines(s, repository);
|
||||||
@@ -291,22 +291,17 @@ VcsOutputWindow::VcsOutputWindow()
|
|||||||
Q_ASSERT(d->passwordRegExp.isValid());
|
Q_ASSERT(d->passwordRegExp.isValid());
|
||||||
m_instance = this;
|
m_instance = this;
|
||||||
|
|
||||||
auto updateFontSettings = [] {
|
|
||||||
d->widget.setBaseFont(TextEditor::TextEditorSettings::fontSettings().font());
|
|
||||||
};
|
|
||||||
|
|
||||||
auto updateBehaviorSettings = [] {
|
auto updateBehaviorSettings = [] {
|
||||||
d->widget.setWheelZoomEnabled(
|
d->widget.setWheelZoomEnabled(
|
||||||
TextEditor::TextEditorSettings::behaviorSettings().m_scrollWheelZooming);
|
TextEditor::TextEditorSettings::behaviorSettings().m_scrollWheelZooming);
|
||||||
};
|
};
|
||||||
|
|
||||||
updateFontSettings();
|
|
||||||
updateBehaviorSettings();
|
updateBehaviorSettings();
|
||||||
|
setupContext(Internal::C_VCS_OUTPUT_PANE, &d->widget);
|
||||||
|
|
||||||
connect(this, &IOutputPane::zoomIn, &d->widget, &Core::OutputWindow::zoomIn);
|
connect(this, &IOutputPane::zoomIn, &d->widget, &Core::OutputWindow::zoomIn);
|
||||||
connect(this, &IOutputPane::zoomOut, &d->widget, &Core::OutputWindow::zoomOut);
|
connect(this, &IOutputPane::zoomOut, &d->widget, &Core::OutputWindow::zoomOut);
|
||||||
connect(TextEditor::TextEditorSettings::instance(), &TextEditor::TextEditorSettings::fontSettingsChanged,
|
connect(this, &IOutputPane::resetZoom, &d->widget, &Core::OutputWindow::resetZoom);
|
||||||
this, updateFontSettings);
|
|
||||||
connect(TextEditor::TextEditorSettings::instance(), &TextEditor::TextEditorSettings::behaviorSettingsChanged,
|
connect(TextEditor::TextEditorSettings::instance(), &TextEditor::TextEditorSettings::behaviorSettingsChanged,
|
||||||
this, updateBehaviorSettings);
|
this, updateBehaviorSettings);
|
||||||
}
|
}
|
||||||
|