Merge remote-tracking branch 'origin/14.0'
Conflicts: src/plugins/qmljseditor/qmljseditingsettingspage.cpp src/plugins/qmljseditor/qmllssettings.h Change-Id: I49b97101467a6e80653c0f5f3e3fe5801dca5274
@@ -1119,27 +1119,3 @@ function(qtc_add_public_header header)
|
|||||||
COMPONENT Devel EXCLUDE_FROM_ALL
|
COMPONENT Devel EXCLUDE_FROM_ALL
|
||||||
)
|
)
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
function (add_qtc_lua_plugin name)
|
|
||||||
cmake_parse_arguments(_arg "EXCLUDE_FROM_INSTALL" "" "SOURCES" ${ARGN})
|
|
||||||
|
|
||||||
if (${_arg_UNPARSED_ARGUMENTS})
|
|
||||||
message(FATAL_ERROR "add_qtc_lua_plugin had unparsed arguments!")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
qtc_copy_to_builddir(${name}
|
|
||||||
FILES ${_arg_SOURCES}
|
|
||||||
DESTINATION ${IDE_PLUGIN_PATH}
|
|
||||||
)
|
|
||||||
|
|
||||||
if (NOT _arg_EXCLUDE_FROM_INSTALL)
|
|
||||||
foreach(SOURCE ${_arg_SOURCES})
|
|
||||||
get_filename_component(SOURCE_DIR "${SOURCE}" DIRECTORY)
|
|
||||||
|
|
||||||
install(
|
|
||||||
FILES ${CMAKE_CURRENT_SOURCE_DIR}/${SOURCE}
|
|
||||||
DESTINATION ${IDE_PLUGIN_PATH}/${SOURCE_DIR}
|
|
||||||
)
|
|
||||||
endforeach()
|
|
||||||
endif()
|
|
||||||
endfunction()
|
|
||||||
|
11
dist/changelog/changes-14.0.0.md
vendored
@@ -131,9 +131,10 @@ Editing
|
|||||||
Projects
|
Projects
|
||||||
--------
|
--------
|
||||||
|
|
||||||
* Added the option to hide all unconfigured kits from the list in `Projects`
|
* Added the `Hide Inactive Kits`/`Show All Kits` button to hide inactive kits
|
||||||
mode
|
from the list in the `Projects` mode
|
||||||
* Added support for user comments in the environment editor
|
* Added support for user comments in the environment editor
|
||||||
|
([Documentation](https://doc-snapshots.qt.io/qtcreator-14.0/creator-how-to-edit-environment-settings.html))
|
||||||
* Fixed the parsing of file links when color was used for the output
|
* Fixed the parsing of file links when color was used for the output
|
||||||
([QTCREATORBUG-30774](https://bugreports.qt.io/browse/QTCREATORBUG-30774))
|
([QTCREATORBUG-30774](https://bugreports.qt.io/browse/QTCREATORBUG-30774))
|
||||||
* Fixed that the column information was not used when opening files from links
|
* Fixed that the column information was not used when opening files from links
|
||||||
@@ -148,7 +149,7 @@ Projects
|
|||||||
|
|
||||||
* Made CMake settings configurable per project
|
* Made CMake settings configurable per project
|
||||||
* Implemented `Open Online Documentation` for CMake documentation
|
* Implemented `Open Online Documentation` for CMake documentation
|
||||||
* Added `Clear CMake Configuration` to the context menu in the Projects view
|
* Added `Clear CMake Configuration` to the context menu in the `Projects` view
|
||||||
([QTCREATORBUG-24658](https://bugreports.qt.io/browse/QTCREATORBUG-24658))
|
([QTCREATORBUG-24658](https://bugreports.qt.io/browse/QTCREATORBUG-24658))
|
||||||
* Fixed that the package manager auto-setup files were not removed with
|
* Fixed that the package manager auto-setup files were not removed with
|
||||||
`Clear CMake Configuration`
|
`Clear CMake Configuration`
|
||||||
@@ -162,7 +163,11 @@ Projects
|
|||||||
[QTCREATORBUG-29559](https://bugreports.qt.io/browse/QTCREATORBUG-29559),
|
[QTCREATORBUG-29559](https://bugreports.qt.io/browse/QTCREATORBUG-29559),
|
||||||
[QTCREATORBUG-30385](https://bugreports.qt.io/browse/QTCREATORBUG-30385))
|
[QTCREATORBUG-30385](https://bugreports.qt.io/browse/QTCREATORBUG-30385))
|
||||||
* Made it possible to register debuggers
|
* Made it possible to register debuggers
|
||||||
|
([QTCREATORBUG-30836](https://bugreports.qt.io/browse/QTCREATORBUG-30836))
|
||||||
* Added support for custom build types
|
* Added support for custom build types
|
||||||
|
([QTCREATORBUG-30014](https://bugreports.qt.io/browse/QTCREATORBUG-30014))
|
||||||
|
|
||||||
|
([Documentation](https://doc-snapshots.qt.io/qtcreator-14.0/creator-build-settings-cmake-presets.html))
|
||||||
|
|
||||||
### Workspace
|
### Workspace
|
||||||
|
|
||||||
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 6.2 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 15 KiB |
BIN
doc/qtcreator/images/qtcreator-project-settings-cmake.webp
Normal file
After Width: | Height: | Size: 3.4 KiB |
Before Width: | Height: | Size: 6.4 KiB After Width: | Height: | Size: 7.5 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 18 KiB |
@@ -57,12 +57,26 @@
|
|||||||
},
|
},
|
||||||
"environment": {
|
"environment": {
|
||||||
"AN_ENVIRONMENT_FLAG": "1"
|
"AN_ENVIRONMENT_FLAG": "1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"vendor": {
|
||||||
|
"qt.io/QtCreator/1.0": {
|
||||||
|
"AskBeforePresetsReload": false,
|
||||||
|
"AskReConfigureInitialParams": false,
|
||||||
|
"AutorunCMake": false,
|
||||||
|
"PackageManagerAutoSetup": false,
|
||||||
|
"ShowAdvancedOptionsByDefault": true,
|
||||||
|
"ShowSourceSubFolders": false,
|
||||||
|
"UseJunctionsForSourceAndBuildDirectories": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
\endcode
|
\endcode
|
||||||
|
|
||||||
|
For more information about the CMake project settings in the \c vendor
|
||||||
|
section, see \l {Override CMake settings for a project}.
|
||||||
|
|
||||||
\section1 MinGW Example
|
\section1 MinGW Example
|
||||||
|
|
||||||
The following example configures a Qt project with:
|
The following example configures a Qt project with:
|
||||||
@@ -74,6 +88,7 @@
|
|||||||
\li generator – MinGW Makefiles
|
\li generator – MinGW Makefiles
|
||||||
\li path to a CMake executable
|
\li path to a CMake executable
|
||||||
\li path to the Qt installation via \c CMAKE_PREFIX_PATH
|
\li path to the Qt installation via \c CMAKE_PREFIX_PATH
|
||||||
|
\li GNU gdb 11.2.0 for MinGW 11.2.0 64-bit debugger
|
||||||
\endlist
|
\endlist
|
||||||
|
|
||||||
\badcode
|
\badcode
|
||||||
@@ -92,8 +107,17 @@
|
|||||||
},
|
},
|
||||||
"environment": {
|
"environment": {
|
||||||
"PATH": "C:/Qt/Tools/mingw1120_64/bin;$penv{PATH}"
|
"PATH": "C:/Qt/Tools/mingw1120_64/bin;$penv{PATH}"
|
||||||
}
|
},
|
||||||
}
|
"vendor": {
|
||||||
|
"qt.io/QtCreator/1.0": {
|
||||||
|
"debugger": {
|
||||||
|
"DisplayName": "GNU gdb 11.2.0 for MinGW 11.2.0 64-bit",
|
||||||
|
"Abis": ["x86-windows-msys-pe-64bit"],
|
||||||
|
"Binary": "C:/Qt/Tools/mingw1120_64/bin/gdb.exe",
|
||||||
|
"EngineType": 1,
|
||||||
|
"Version": "11.2.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
\endcode
|
\endcode
|
||||||
@@ -188,6 +212,50 @@
|
|||||||
}
|
}
|
||||||
\endcode
|
\endcode
|
||||||
|
|
||||||
|
\section1 Cross-Compilation Example
|
||||||
|
|
||||||
|
The following example configures a Qt project for cross-compilation on \macos
|
||||||
|
for Windows and running with the \c wine emulator on \macos:
|
||||||
|
|
||||||
|
\list
|
||||||
|
\li generator – Ninja
|
||||||
|
\li build directory – \c <sourceDir>/build-release
|
||||||
|
\li LLVM/MinGW toolchain
|
||||||
|
\li configuration type – \c CMAKE_BUILD_TYPE as \c Release
|
||||||
|
\li LLDB 18.1.6 debugger
|
||||||
|
\li \c wine emulator
|
||||||
|
\endlist
|
||||||
|
|
||||||
|
\badcode
|
||||||
|
{
|
||||||
|
"version": 4,
|
||||||
|
"configurePresets": [
|
||||||
|
{
|
||||||
|
"name": "llvm-mingw",
|
||||||
|
"displayName": "LLVM-MinGW 18.1.6",
|
||||||
|
"generator": "Ninja",
|
||||||
|
"binaryDir": "${sourceDir}/build-release",
|
||||||
|
"toolchainFile": "llvm-mingw.cmake",
|
||||||
|
"cacheVariables": {
|
||||||
|
"CMAKE_BUILD_TYPE": "Release",
|
||||||
|
"CMAKE_CROSSCOMPILING_EMULATOR": "/opt/homebrew/bin/wine"
|
||||||
|
},
|
||||||
|
"vendor": {
|
||||||
|
"qt.io/QtCreator/1.0": {
|
||||||
|
"debugger": {
|
||||||
|
"DisplayName": "LLDB 18.1.6 (CMake Preset)",
|
||||||
|
"Abis": ["x86-darwin-generic-mach_o-64bit", "arm-darwin-generic-mach_o-64bit"],
|
||||||
|
"Binary": "/Users/jdoe/llvm-mingw/bin/lldb",
|
||||||
|
"EngineType": 256,
|
||||||
|
"Version": "18.1.6"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
\endcode
|
||||||
|
|
||||||
\section1 Using Conditions
|
\section1 Using Conditions
|
||||||
|
|
||||||
The following configure presets are used if they match \c condition. That is,
|
The following configure presets are used if they match \c condition. That is,
|
||||||
|
@@ -65,8 +65,7 @@
|
|||||||
a tree and lists all files that are part of the project.
|
a tree and lists all files that are part of the project.
|
||||||
\QC automatically runs CMake to refresh project information in the
|
\QC automatically runs CMake to refresh project information in the
|
||||||
view when you edit a \c CMakeLists.txt configuration file
|
view when you edit a \c CMakeLists.txt configuration file
|
||||||
in a project. Project information is also automatically refreshed when
|
in a project. Also, refreshes project information when you build the project.
|
||||||
you build the project.
|
|
||||||
|
|
||||||
\image qtcreator-projects-view-edit.png {CMake project in Projects view}
|
\image qtcreator-projects-view-edit.png {CMake project in Projects view}
|
||||||
|
|
||||||
|
75
doc/qtcreator/src/cmake/creator-projects-settings-cmake.qdoc
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
// Copyright (C) 2024 The Qt Company Ltd.
|
||||||
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\page creator-how-to-configure-cmake-for-project.html
|
||||||
|
\previouspage creator-how-tos.html
|
||||||
|
|
||||||
|
\ingroup creator-how-to-projects-configure
|
||||||
|
\ingroup creator-how-to-build-with-cmake
|
||||||
|
|
||||||
|
\title Override CMake settings for a project
|
||||||
|
|
||||||
|
To override CMake settings for the current project:
|
||||||
|
|
||||||
|
\list 1
|
||||||
|
\li Go to \uicontrol Projects > \uicontrol {Project Settings} >
|
||||||
|
\uicontrol CMake.
|
||||||
|
\image qtcreator-project-settings-cmake.webp {CMake settings for a project}
|
||||||
|
\li Clear \uicontrol {Use global settings}.
|
||||||
|
\li Configure CMake for the project.
|
||||||
|
\endlist
|
||||||
|
|
||||||
|
Your choices override the values you set in \preferences > \uicontrol CMake >
|
||||||
|
\uicontrol General.
|
||||||
|
|
||||||
|
\table
|
||||||
|
\header
|
||||||
|
\li Setting
|
||||||
|
\li Value
|
||||||
|
\li Read More
|
||||||
|
\row
|
||||||
|
\li Autorun CMake
|
||||||
|
\li Runs CMake to refresh project information when you edit
|
||||||
|
a \c CMakeLists.txt configuration file in a project. Also,
|
||||||
|
refreshes project information when you build the project.
|
||||||
|
\li \l{View CMake project contents}
|
||||||
|
\row
|
||||||
|
\li Package manager auto setup
|
||||||
|
\li Sets up the \l {Conan Package Manager}{Conan} or
|
||||||
|
\l {vcpkg Package Manager}{vcpkg} package manager for use with CMake.
|
||||||
|
\li \l{Using CMake with Package Managers}
|
||||||
|
\row
|
||||||
|
\li Ask before re-configuring with initial parameters
|
||||||
|
\li Asks before acting when you select
|
||||||
|
\uicontrol {Re-configure with Initial Variables}.
|
||||||
|
\li \l{Re-configuring with Initial Variables}
|
||||||
|
\row
|
||||||
|
\li Ask before reloading CMake presets
|
||||||
|
\li Asks before acting when you select \uicontrol Build >
|
||||||
|
\uicontrol {Reload CMake Presets}.
|
||||||
|
\li \l{CMake Presets}
|
||||||
|
\row
|
||||||
|
\li Show subfolders inside source group folders
|
||||||
|
\li Hides subfolder names and arranges the files according to their
|
||||||
|
source group in the \uicontrol Projects view.
|
||||||
|
\li \l{Hide subfolder names in Projects view}
|
||||||
|
\row
|
||||||
|
\li Show advanced options by default
|
||||||
|
\li Shows all CMake variables by default in
|
||||||
|
\uicontrol {Initial Configuration} and
|
||||||
|
\uicontrol {Current Configuration}.
|
||||||
|
\li \l{Viewing Advanced Variables}
|
||||||
|
\row
|
||||||
|
\li Use junctions for CMake configuration and build operations
|
||||||
|
\li On Windows, uses junction points for CMake configure, build, and
|
||||||
|
install operations.
|
||||||
|
\li \l{Using Junction Points on Windows}
|
||||||
|
\endtable
|
||||||
|
|
||||||
|
You can set these preferences as \l{Configure Presets}{CMake presets} or in
|
||||||
|
a \l{Share project settings}{CMakeLists.txt.shared} file.
|
||||||
|
|
||||||
|
\sa {Build with CMake}{How To: Build with CMake}, {CMake},
|
||||||
|
{Configuring Projects}
|
||||||
|
*/
|
@@ -44,9 +44,16 @@
|
|||||||
Then, you must edit the build settings of the project to specify the
|
Then, you must edit the build settings of the project to specify the
|
||||||
location of the file and the contents of the Conan install command.
|
location of the file and the contents of the Conan install command.
|
||||||
|
|
||||||
Alternatively, you can automatically set up the Conan package manager for
|
\section1 Automatic Package Manager Setup
|
||||||
use with CMake.
|
|
||||||
|
To automatically set up the Conan package manager for use with CMake,
|
||||||
|
go to \uicontrol Projects > \uicontrol {Project Settings} > \uicontrol CMake,
|
||||||
|
and select \uicontrol {Package manager auto setup}.
|
||||||
|
|
||||||
|
To turn off the automatic package manager setup, set
|
||||||
|
\c PackageManagerAutoSetup to \c false in \l{Configure Presets}
|
||||||
|
{CMake presets} or a \l{Share project settings}{CMakeLists.txt.shared} file.
|
||||||
|
|
||||||
\sa {Conan Build Configuration}, {Enable and disable plugins},
|
\sa {Conan Build Configuration}, {Enable and disable plugins},
|
||||||
{Using CMake with Package Managers}
|
{Override CMake settings for a project}, {Using CMake with Package Managers}
|
||||||
*/
|
*/
|
||||||
|
@@ -255,6 +255,9 @@
|
|||||||
\QMLLS of the highest registered Qt version, select
|
\QMLLS of the highest registered Qt version, select
|
||||||
\uicontrol {Use \QMLLS from latest Qt version}.
|
\uicontrol {Use \QMLLS from latest Qt version}.
|
||||||
|
|
||||||
|
To use older \QMLLS versions, select
|
||||||
|
\uicontrol{Allow versions below Qt 6.8}.
|
||||||
|
|
||||||
\image qtcreator-qml-js-editing.webp {QML/JS Editing preferences}
|
\image qtcreator-qml-js-editing.webp {QML/JS Editing preferences}
|
||||||
|
|
||||||
When using \c qmlls from Qt 6.7 or later, set \l{QT_QML_GENERATE_QMLLS_INI}
|
When using \c qmlls from Qt 6.7 or later, set \l{QT_QML_GENERATE_QMLLS_INI}
|
||||||
|
@@ -84,6 +84,7 @@
|
|||||||
\li \l{Link projects to Axivion dashboards}{Axivion}
|
\li \l{Link projects to Axivion dashboards}{Axivion}
|
||||||
\li \l{Specify clangd settings}{Clangd}
|
\li \l{Specify clangd settings}{Clangd}
|
||||||
\li \l{Specify Clang tools settings}{Clang Tools}
|
\li \l{Specify Clang tools settings}{Clang Tools}
|
||||||
|
\li \l{Override CMake settings for a project}{CMake}
|
||||||
\li \l{Set Copilot preferences}{Copilot}
|
\li \l{Set Copilot preferences}{Copilot}
|
||||||
\li \l{Configure C++ code model}{C++ Code Model}
|
\li \l{Configure C++ code model}{C++ Code Model}
|
||||||
\li \l{Specify code style}{C++ Code Style}
|
\li \l{Specify code style}{C++ Code Style}
|
||||||
@@ -127,6 +128,9 @@
|
|||||||
is not suitable for the project type. To view the warning and error messages,
|
is not suitable for the project type. To view the warning and error messages,
|
||||||
move the mouse pointer over the kit name.
|
move the mouse pointer over the kit name.
|
||||||
|
|
||||||
|
To hide inactive kits from the list, select \uicontrol {Hide Inactive Kits}.
|
||||||
|
To show them again, select \uicontrol {Show All Kits}.
|
||||||
|
|
||||||
\section1 Manage kits
|
\section1 Manage kits
|
||||||
|
|
||||||
To modify kit configuration or to \l{Add kits}{add kits} to the list or to
|
To modify kit configuration or to \l{Add kits}{add kits} to the list or to
|
||||||
|
@@ -20,7 +20,8 @@
|
|||||||
has the same XML structure as a \e {.user} file, but only has the
|
has the same XML structure as a \e {.user} file, but only has the
|
||||||
settings to share.
|
settings to share.
|
||||||
|
|
||||||
\note Use \l{CMake Presets} to share CMake project settings.
|
To share CMake project settings, use \l{CMake Presets} or a
|
||||||
|
\c {CMakeLists.txt.shared} file.
|
||||||
|
|
||||||
\section1 Create a shared settings file
|
\section1 Create a shared settings file
|
||||||
|
|
||||||
@@ -72,5 +73,38 @@
|
|||||||
a permanent sticky setting that was created just because you wanted to try
|
a permanent sticky setting that was created just because you wanted to try
|
||||||
something out.
|
something out.
|
||||||
|
|
||||||
|
\section1 Share CMake project settings
|
||||||
|
|
||||||
|
The following is an example of a \c {CMakeLists.txt.shared} file:
|
||||||
|
|
||||||
|
\badcode
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE QtCreatorProject>
|
||||||
|
<qtcreator>
|
||||||
|
<data>
|
||||||
|
<variable>ProjectExplorer.Project.PluginSettings</variable>
|
||||||
|
<valuemap type="QVariantMap">
|
||||||
|
<valuemap type="QVariantMap" key="CMakeSpecificSettings">
|
||||||
|
<value type="bool" key="AskBeforePresetsReload">false</value>
|
||||||
|
<value type="bool" key="AskReConfigureInitialParams">false</value>
|
||||||
|
<value type="bool" key="AutorunCMake">false</value>
|
||||||
|
<value type="bool" key="PackageManagerAutoSetup">false</value>
|
||||||
|
<value type="bool" key="ShowAdvancedOptionsByDefault">true</value>
|
||||||
|
<value type="bool" key="ShowSourceSubFolders">false</value>
|
||||||
|
<value type="bool" key="UseGlobalSettings">false</value>
|
||||||
|
<value type="bool" key="UseJunctionsForSourceAndBuildDirectories">true</value>
|
||||||
|
</valuemap>
|
||||||
|
</valuemap>
|
||||||
|
</data>
|
||||||
|
<data>
|
||||||
|
<variable>Version</variable>
|
||||||
|
<value type="int">22</value>
|
||||||
|
</data>
|
||||||
|
</qtcreator>
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
For more information about the settings, see
|
||||||
|
\l {Override CMake settings for a project}.
|
||||||
|
|
||||||
\sa {Configuring Projects}, {CMake Presets}
|
\sa {Configuring Projects}, {CMake Presets}
|
||||||
*/
|
*/
|
||||||
|
@@ -1,12 +0,0 @@
|
|||||||
Product {
|
|
||||||
Depends { name: "qtc" }
|
|
||||||
|
|
||||||
property stringList luafiles
|
|
||||||
|
|
||||||
Group {
|
|
||||||
prefix: sourceDirectory + '/' + product.name + '/'
|
|
||||||
files: luafiles
|
|
||||||
qbs.install: true
|
|
||||||
qbs.installDir: qtc.ide_plugin_path + '/' + product.name
|
|
||||||
}
|
|
||||||
}
|
|
@@ -618,11 +618,11 @@
|
|||||||
"QDocModule": "qtcreator",
|
"QDocModule": "qtcreator",
|
||||||
"QtParts": ["tools"],
|
"QtParts": ["tools"],
|
||||||
"QtUsage": "Used for pretty printing from Lua scripts.",
|
"QtUsage": "Used for pretty printing from Lua scripts.",
|
||||||
"Path": "src/plugins/luatests/luatests",
|
"Path": "share/qtcreator/lua-plugins/luatests",
|
||||||
"Description": "inspect.lua is a library for pretty printing complex objects in Lua.",
|
"Description": "inspect.lua is a library for pretty printing complex objects in Lua.",
|
||||||
"Homepage": "https://github.com/kikito/inspect.lua",
|
"Homepage": "https://github.com/kikito/inspect.lua",
|
||||||
"License": "MIT License",
|
"License": "MIT License",
|
||||||
"LicenseFile": "src/plugins/luatests/luatests/INSPECT-LICENSE.txt",
|
"LicenseFile": "share/qtcreator/lua-plugins/luatests/INSPECT-LICENSE.txt",
|
||||||
"Copyright": "Copyright (c) 2022 Enrique García Cota"
|
"Copyright": "Copyright (c) 2022 Enrique García Cota"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@@ -4,6 +4,7 @@ set(resource_directories
|
|||||||
glsl
|
glsl
|
||||||
indexer_preincludes
|
indexer_preincludes
|
||||||
jsonschemas
|
jsonschemas
|
||||||
|
lua-plugins
|
||||||
modeleditor
|
modeleditor
|
||||||
qmldesigner
|
qmldesigner
|
||||||
qmlicons
|
qmlicons
|
||||||
@@ -19,6 +20,7 @@ set(resource_files
|
|||||||
debugger/.pylintrc
|
debugger/.pylintrc
|
||||||
debugger/boosttypes.py
|
debugger/boosttypes.py
|
||||||
debugger/cdbbridge.py
|
debugger/cdbbridge.py
|
||||||
|
debugger/cdbext.pyi
|
||||||
debugger/creatortypes.py
|
debugger/creatortypes.py
|
||||||
debugger/dumper.py
|
debugger/dumper.py
|
||||||
debugger/gdbbridge.py
|
debugger/gdbbridge.py
|
||||||
|
@@ -85,12 +85,12 @@ class Dumper(DumperBase):
|
|||||||
del self.type_size_cache[typeid]
|
del self.type_size_cache[typeid]
|
||||||
del self.type_alignment_cache[typeid]
|
del self.type_alignment_cache[typeid]
|
||||||
|
|
||||||
def enumValue(self, nativeValue):
|
def enumValue(self, nativeValue: cdbext.Value) -> str:
|
||||||
val = nativeValue.nativeDebuggerValue()
|
val = nativeValue.nativeDebuggerValue()
|
||||||
# remove '0n' decimal prefix of the native cdb value output
|
# remove '0n' decimal prefix of the native cdb value output
|
||||||
return val.replace('(0n', '(')
|
return val.replace('(0n', '(')
|
||||||
|
|
||||||
def fromNativeValue(self, nativeValue):
|
def fromNativeValue(self, nativeValue: cdbext.Value) -> DumperBase.Value:
|
||||||
self.check(isinstance(nativeValue, cdbext.Value))
|
self.check(isinstance(nativeValue, cdbext.Value))
|
||||||
val = self.Value(self)
|
val = self.Value(self)
|
||||||
val.name = nativeValue.name()
|
val.name = nativeValue.name()
|
||||||
@@ -133,7 +133,7 @@ class Dumper(DumperBase):
|
|||||||
val.lbitsize = nativeValue.bitsize()
|
val.lbitsize = nativeValue.bitsize()
|
||||||
return val
|
return val
|
||||||
|
|
||||||
def nativeTypeId(self, nativeType):
|
def nativeTypeId(self, nativeType: cdbext.Type) -> str:
|
||||||
self.check(isinstance(nativeType, cdbext.Type))
|
self.check(isinstance(nativeType, cdbext.Type))
|
||||||
name = nativeType.name()
|
name = nativeType.name()
|
||||||
if name is None or len(name) == 0:
|
if name is None or len(name) == 0:
|
||||||
@@ -148,7 +148,7 @@ class Dumper(DumperBase):
|
|||||||
for f in nativeType.fields()])
|
for f in nativeType.fields()])
|
||||||
return typeId
|
return typeId
|
||||||
|
|
||||||
def from_native_type(self, nativeType):
|
def from_native_type(self, nativeType: cdbext.Type) -> str:
|
||||||
self.check(isinstance(nativeType, cdbext.Type))
|
self.check(isinstance(nativeType, cdbext.Type))
|
||||||
typeid = self.typeid_for_string(self.nativeTypeId(nativeType))
|
typeid = self.typeid_for_string(self.nativeTypeId(nativeType))
|
||||||
self.type_nativetype_cache[typeid] = nativeType
|
self.type_nativetype_cache[typeid] = nativeType
|
||||||
@@ -187,7 +187,7 @@ class Dumper(DumperBase):
|
|||||||
self.nativeTypeEnumDisplay(nativeType, intval, form)
|
self.nativeTypeEnumDisplay(nativeType, intval, form)
|
||||||
return typeid
|
return typeid
|
||||||
|
|
||||||
def listNativeValueChildren(self, nativeValue, include_bases):
|
def listNativeValueChildren(self, nativeValue: cdbext.Value, include_bases: bool) -> list[DumperBase.Value]:
|
||||||
fields = []
|
fields = []
|
||||||
index = 0
|
index = 0
|
||||||
nativeMember = nativeValue.childFromIndex(index)
|
nativeMember = nativeValue.childFromIndex(index)
|
||||||
@@ -202,19 +202,19 @@ class Dumper(DumperBase):
|
|||||||
nativeMember = nativeValue.childFromIndex(index)
|
nativeMember = nativeValue.childFromIndex(index)
|
||||||
return fields
|
return fields
|
||||||
|
|
||||||
def listValueChildren(self, value, include_bases=True):
|
def listValueChildren(self, value: DumperBase.Value, include_bases=True) -> list[DumperBase.Value]:
|
||||||
nativeValue = value.nativeValue
|
nativeValue = value.nativeValue
|
||||||
if nativeValue is None:
|
if nativeValue is None:
|
||||||
nativeValue = cdbext.createValue(value.address(), self.lookupNativeType(value.type.name, 0))
|
nativeValue = cdbext.createValue(value.address(), self.lookupNativeType(value.type.name, 0))
|
||||||
return self.listNativeValueChildren(nativeValue, include_bases)
|
return self.listNativeValueChildren(nativeValue, include_bases)
|
||||||
|
|
||||||
def nativeListMembers(self, value, native_type, include_bases):
|
def nativeListMembers(self, value: DumperBase.Value, native_type: cdbext.Type, include_bases: bool) -> list[DumperBase.Value]:
|
||||||
nativeValue = value.nativeValue
|
nativeValue = value.nativeValue
|
||||||
if nativeValue is None:
|
if nativeValue is None:
|
||||||
nativeValue = cdbext.createValue(value.address(), native_type)
|
nativeValue = cdbext.createValue(value.address(), native_type)
|
||||||
return self.listNativeValueChildren(nativeValue, include_bases)
|
return self.listNativeValueChildren(nativeValue, include_bases)
|
||||||
|
|
||||||
def nativeStructAlignment(self, nativeType):
|
def nativeStructAlignment(self, nativeType: cdbext.Type) -> int:
|
||||||
#DumperBase.warn("NATIVE ALIGN FOR %s" % nativeType.name)
|
#DumperBase.warn("NATIVE ALIGN FOR %s" % nativeType.name)
|
||||||
def handleItem(nativeFieldType, align):
|
def handleItem(nativeFieldType, align):
|
||||||
a = self.type_alignment(self.from_native_type(nativeFieldType))
|
a = self.type_alignment(self.from_native_type(nativeFieldType))
|
||||||
@@ -224,13 +224,13 @@ class Dumper(DumperBase):
|
|||||||
align = handleItem(f.type(), align)
|
align = handleItem(f.type(), align)
|
||||||
return align
|
return align
|
||||||
|
|
||||||
def nativeTypeEnumDisplay(self, nativeType, intval, form):
|
def nativeTypeEnumDisplay(self, nativeType: cdbext.Type, intval: int, form) -> str:
|
||||||
value = self.nativeParseAndEvaluate('(%s)%d' % (nativeType.name(), intval))
|
value = self.nativeParseAndEvaluate('(%s)%d' % (nativeType.name(), intval))
|
||||||
if value is None:
|
if value is None:
|
||||||
return ''
|
return ''
|
||||||
return self.enumValue(value)
|
return self.enumValue(value)
|
||||||
|
|
||||||
def enumExpression(self, enumType, enumValue):
|
def enumExpression(self, enumType: str, enumValue: str) -> str:
|
||||||
ns = self.qtNamespace()
|
ns = self.qtNamespace()
|
||||||
return ns + "Qt::" + enumType + "(" \
|
return ns + "Qt::" + enumType + "(" \
|
||||||
+ ns + "Qt::" + enumType + "::" + enumValue + ")"
|
+ ns + "Qt::" + enumType + "::" + enumValue + ")"
|
||||||
@@ -238,25 +238,25 @@ class Dumper(DumperBase):
|
|||||||
def pokeValue(self, typeName, *args):
|
def pokeValue(self, typeName, *args):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def parseAndEvaluate(self, exp):
|
def parseAndEvaluate(self, exp: str) -> DumperBase.Value:
|
||||||
return self.fromNativeValue(self.nativeParseAndEvaluate(exp))
|
return self.fromNativeValue(self.nativeParseAndEvaluate(exp))
|
||||||
|
|
||||||
def nativeParseAndEvaluate(self, exp):
|
def nativeParseAndEvaluate(self, exp: str) -> cdbext.Value:
|
||||||
return cdbext.parseAndEvaluate(exp)
|
return cdbext.parseAndEvaluate(exp)
|
||||||
|
|
||||||
def isWindowsTarget(self):
|
def isWindowsTarget(self) -> bool:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def isQnxTarget(self):
|
def isQnxTarget(self) -> bool:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def isArmArchitecture(self):
|
def isArmArchitecture(self) -> bool:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def isMsvcTarget(self):
|
def isMsvcTarget(self) -> bool:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def qtCoreModuleName(self):
|
def qtCoreModuleName(self) -> str:
|
||||||
modules = cdbext.listOfModules()
|
modules = cdbext.listOfModules()
|
||||||
# first check for an exact module name match
|
# first check for an exact module name match
|
||||||
for coreName in ['Qt6Core', 'Qt6Cored', 'Qt5Cored', 'Qt5Core', 'QtCored4', 'QtCore4']:
|
for coreName in ['Qt6Core', 'Qt6Cored', 'Qt5Cored', 'Qt5Core', 'QtCored4', 'QtCore4']:
|
||||||
@@ -272,7 +272,7 @@ class Dumper(DumperBase):
|
|||||||
return coreName
|
return coreName
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def qtDeclarativeModuleName(self):
|
def qtDeclarativeModuleName(self) -> str:
|
||||||
modules = cdbext.listOfModules()
|
modules = cdbext.listOfModules()
|
||||||
for declarativeModuleName in ['Qt6Qmld', 'Qt6Qml', 'Qt5Qmld', 'Qt5Qml']:
|
for declarativeModuleName in ['Qt6Qmld', 'Qt6Qml', 'Qt5Qmld', 'Qt5Qml']:
|
||||||
if declarativeModuleName in modules:
|
if declarativeModuleName in modules:
|
||||||
@@ -285,7 +285,7 @@ class Dumper(DumperBase):
|
|||||||
return declarativeModuleName
|
return declarativeModuleName
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def qtHookDataSymbolName(self):
|
def qtHookDataSymbolName(self) -> str:
|
||||||
hookSymbolName = 'qtHookData'
|
hookSymbolName = 'qtHookData'
|
||||||
coreModuleName = self.qtCoreModuleName()
|
coreModuleName = self.qtCoreModuleName()
|
||||||
if coreModuleName is not None:
|
if coreModuleName is not None:
|
||||||
@@ -299,7 +299,7 @@ class Dumper(DumperBase):
|
|||||||
self.qtHookDataSymbolName = lambda: hookSymbolName
|
self.qtHookDataSymbolName = lambda: hookSymbolName
|
||||||
return hookSymbolName
|
return hookSymbolName
|
||||||
|
|
||||||
def qtDeclarativeHookDataSymbolName(self):
|
def qtDeclarativeHookDataSymbolName(self) -> str:
|
||||||
hookSymbolName = 'qtDeclarativeHookData'
|
hookSymbolName = 'qtDeclarativeHookData'
|
||||||
declarativeModuleName = self.qtDeclarativeModuleName()
|
declarativeModuleName = self.qtDeclarativeModuleName()
|
||||||
if declarativeModuleName is not None:
|
if declarativeModuleName is not None:
|
||||||
@@ -314,7 +314,7 @@ class Dumper(DumperBase):
|
|||||||
self.qtDeclarativeHookDataSymbolName = lambda: hookSymbolName
|
self.qtDeclarativeHookDataSymbolName = lambda: hookSymbolName
|
||||||
return hookSymbolName
|
return hookSymbolName
|
||||||
|
|
||||||
def extractQtVersion(self):
|
def extractQtVersion(self) -> int:
|
||||||
try:
|
try:
|
||||||
qtVersion = self.parseAndEvaluate(
|
qtVersion = self.parseAndEvaluate(
|
||||||
'((void**)&%s)[2]' % self.qtHookDataSymbolName()).integer()
|
'((void**)&%s)[2]' % self.qtHookDataSymbolName()).integer()
|
||||||
@@ -329,7 +329,7 @@ class Dumper(DumperBase):
|
|||||||
return None
|
return None
|
||||||
return qtVersion
|
return qtVersion
|
||||||
|
|
||||||
def putVtableItem(self, address):
|
def putVtableItem(self, address: int):
|
||||||
funcName = cdbext.getNameByAddress(address)
|
funcName = cdbext.getNameByAddress(address)
|
||||||
if funcName is None:
|
if funcName is None:
|
||||||
self.putItem(self.createPointerValue(address, 'void'))
|
self.putItem(self.createPointerValue(address, 'void'))
|
||||||
@@ -338,7 +338,7 @@ class Dumper(DumperBase):
|
|||||||
self.putType('void*')
|
self.putType('void*')
|
||||||
self.putAddress(address)
|
self.putAddress(address)
|
||||||
|
|
||||||
def putVTableChildren(self, item, itemCount):
|
def putVTableChildren(self, item: DumperBase.Value, itemCount: int) -> int:
|
||||||
p = item.address()
|
p = item.address()
|
||||||
for i in range(itemCount):
|
for i in range(itemCount):
|
||||||
deref = self.extractPointer(p)
|
deref = self.extractPointer(p)
|
||||||
@@ -350,12 +350,12 @@ class Dumper(DumperBase):
|
|||||||
p += self.ptrSize()
|
p += self.ptrSize()
|
||||||
return itemCount
|
return itemCount
|
||||||
|
|
||||||
def ptrSize(self):
|
def ptrSize(self) -> int:
|
||||||
size = cdbext.pointerSize()
|
size = cdbext.pointerSize()
|
||||||
self.ptrSize = lambda: size
|
self.ptrSize = lambda: size
|
||||||
return size
|
return size
|
||||||
|
|
||||||
def stripQintTypedefs(self, typeName):
|
def stripQintTypedefs(self, typeName: str) -> str:
|
||||||
if typeName.startswith('qint'):
|
if typeName.startswith('qint'):
|
||||||
prefix = ''
|
prefix = ''
|
||||||
size = typeName[4:]
|
size = typeName[4:]
|
||||||
@@ -375,7 +375,7 @@ class Dumper(DumperBase):
|
|||||||
else:
|
else:
|
||||||
return typeName
|
return typeName
|
||||||
|
|
||||||
def lookupNativeType(self, name, module=0):
|
def lookupNativeType(self, name: str, module=0) -> cdbext.Type:
|
||||||
if name.startswith('void'):
|
if name.startswith('void'):
|
||||||
return FakeVoidType(name, self)
|
return FakeVoidType(name, self)
|
||||||
return cdbext.lookupType(name, module)
|
return cdbext.lookupType(name, module)
|
||||||
@@ -383,13 +383,13 @@ class Dumper(DumperBase):
|
|||||||
def reportResult(self, result, args):
|
def reportResult(self, result, args):
|
||||||
cdbext.reportResult('result={%s}' % result)
|
cdbext.reportResult('result={%s}' % result)
|
||||||
|
|
||||||
def readRawMemory(self, address, size):
|
def readRawMemory(self, address: int, size: int) -> int:
|
||||||
mem = cdbext.readRawMemory(address, size)
|
mem = cdbext.readRawMemory(address, size)
|
||||||
if len(mem) != size:
|
if len(mem) != size:
|
||||||
raise Exception("Invalid memory request: %d bytes from 0x%x" % (size, address))
|
raise Exception("Invalid memory request: %d bytes from 0x%x" % (size, address))
|
||||||
return mem
|
return mem
|
||||||
|
|
||||||
def findStaticMetaObject(self, type):
|
def findStaticMetaObject(self, type: DumperBase.Type) -> int:
|
||||||
ptr = 0
|
ptr = 0
|
||||||
if type.moduleName is not None:
|
if type.moduleName is not None:
|
||||||
# Try to find the static meta object in the same module as the type definition. This is
|
# Try to find the static meta object in the same module as the type definition. This is
|
||||||
@@ -449,13 +449,10 @@ class Dumper(DumperBase):
|
|||||||
def report(self, stuff):
|
def report(self, stuff):
|
||||||
sys.stdout.write(stuff + "\n")
|
sys.stdout.write(stuff + "\n")
|
||||||
|
|
||||||
def findValueByExpression(self, exp):
|
def nativeValueDereferenceReference(self, value: DumperBase.Value) -> DumperBase.Value:
|
||||||
return cdbext.parseAndEvaluate(exp)
|
|
||||||
|
|
||||||
def nativeValueDereferenceReference(self, value):
|
|
||||||
return self.nativeValueDereferencePointer(value)
|
return self.nativeValueDereferencePointer(value)
|
||||||
|
|
||||||
def nativeValueDereferencePointer(self, value):
|
def nativeValueDereferencePointer(self, value: DumperBase.Value) -> DumperBase.Value:
|
||||||
def nativeVtCastValue(nativeValue):
|
def nativeVtCastValue(nativeValue):
|
||||||
# If we have a pointer to a derived instance of the pointer type cdb adds a
|
# If we have a pointer to a derived instance of the pointer type cdb adds a
|
||||||
# synthetic '__vtcast_<derived type name>' member as the first child
|
# synthetic '__vtcast_<derived type name>' member as the first child
|
||||||
@@ -490,7 +487,7 @@ class Dumper(DumperBase):
|
|||||||
def callHelper(self, rettype, value, function, args):
|
def callHelper(self, rettype, value, function, args):
|
||||||
raise Exception("cdb does not support calling functions")
|
raise Exception("cdb does not support calling functions")
|
||||||
|
|
||||||
def nameForCoreId(self, id):
|
def nameForCoreId(self, id: int) -> DumperBase.Value:
|
||||||
for dll in ['Utilsd', 'Utils']:
|
for dll in ['Utilsd', 'Utils']:
|
||||||
idName = cdbext.call('%s!Utils::nameForId(%d)' % (dll, id))
|
idName = cdbext.call('%s!Utils::nameForId(%d)' % (dll, id))
|
||||||
if idName is not None:
|
if idName is not None:
|
||||||
@@ -500,7 +497,7 @@ class Dumper(DumperBase):
|
|||||||
def putCallItem(self, name, rettype, value, func, *args):
|
def putCallItem(self, name, rettype, value, func, *args):
|
||||||
return
|
return
|
||||||
|
|
||||||
def symbolAddress(self, symbolName):
|
def symbolAddress(self, symbolName: str) -> int:
|
||||||
res = self.nativeParseAndEvaluate(symbolName)
|
res = self.nativeParseAndEvaluate(symbolName)
|
||||||
return None if res is None else res.address()
|
return None if res is None else res.address()
|
||||||
|
|
||||||
@@ -726,7 +723,7 @@ class Dumper(DumperBase):
|
|||||||
self.putItem(value.dereference())
|
self.putItem(value.dereference())
|
||||||
|
|
||||||
|
|
||||||
def putCStyleArray(self, value):
|
def putCStyleArray(self, value: DumperBase.Value):
|
||||||
arrayType = value.type
|
arrayType = value.type
|
||||||
innerType = arrayType.target()
|
innerType = arrayType.target()
|
||||||
address = value.address()
|
address = value.address()
|
||||||
@@ -886,26 +883,6 @@ class Dumper(DumperBase):
|
|||||||
self.putItem(derefValue)
|
self.putItem(derefValue)
|
||||||
self.currentChildType = savedCurrentChildType
|
self.currentChildType = savedCurrentChildType
|
||||||
|
|
||||||
def createValue(self, datish, typish):
|
|
||||||
if isinstance(datish, int): # Used as address.
|
|
||||||
return self.createValueFromAddressAndType(datish, typish)
|
|
||||||
if isinstance(datish, bytes):
|
|
||||||
val = self.Value(self)
|
|
||||||
val.typeid = self.create_typeid(typish)
|
|
||||||
#DumperBase.warn('CREATING %s WITH DATA %s' % (val.type.name, self.hexencode(datish)))
|
|
||||||
val.ldata = datish
|
|
||||||
val.check()
|
|
||||||
return val
|
|
||||||
raise RuntimeError('EXPECTING ADDRESS OR BYTES, GOT %s' % type(datish))
|
|
||||||
|
|
||||||
def createValueFromAddressAndType(self, address, typish):
|
|
||||||
val = self.Value(self)
|
|
||||||
val.typeid = self.create_typeid(typish)
|
|
||||||
val.laddress = address
|
|
||||||
if self.useDynamicType:
|
|
||||||
val.typeid = self.dynamic_typeid_at_address(val.typeid, address)
|
|
||||||
return val
|
|
||||||
|
|
||||||
def fetchInternalFunctions(self):
|
def fetchInternalFunctions(self):
|
||||||
coreModuleName = self.qtCoreModuleName()
|
coreModuleName = self.qtCoreModuleName()
|
||||||
ns = self.qtNamespace()
|
ns = self.qtNamespace()
|
||||||
|
51
share/qtcreator/debugger/cdbext.pyi
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
class Type: ...
|
||||||
|
|
||||||
|
class Field:
|
||||||
|
def name(self) -> str : ...
|
||||||
|
def isBaseClass(self) -> bool : ...
|
||||||
|
def type(self) -> Type : ...
|
||||||
|
def parentType(self) -> Type : ...
|
||||||
|
def bitsize(self) -> int : ...
|
||||||
|
def bitpos(self) -> int : ...
|
||||||
|
|
||||||
|
class Type:
|
||||||
|
def name(self) -> str: ...
|
||||||
|
def bitsize(self) -> int : ...
|
||||||
|
def code(self) -> int : ...
|
||||||
|
def unqualified(self) -> bool : ...
|
||||||
|
def target(self) -> Type : ...
|
||||||
|
def targetName(self) -> str : ...
|
||||||
|
def stripTypedef(self) -> Type : ...
|
||||||
|
def fields(self) -> Field : ...
|
||||||
|
def module(self) -> str : ...
|
||||||
|
def moduleId(self) -> int : ...
|
||||||
|
def arrayElements(self) -> int : ...
|
||||||
|
def templateArguments(self) -> list[int | str] : ...
|
||||||
|
def resolved(self) -> bool : ...
|
||||||
|
|
||||||
|
class Value: ...
|
||||||
|
class Value:
|
||||||
|
def name(self) -> str : ...
|
||||||
|
def type(self) -> Type : ...
|
||||||
|
def bitsize(self) -> int : ...
|
||||||
|
def asBytes(self) -> bytes : ...
|
||||||
|
def address(self) -> int : ...
|
||||||
|
def hasChildren(self) -> bool : ...
|
||||||
|
def expand(self) -> bool : ...
|
||||||
|
def nativeDebuggerValue(self) -> str : ...
|
||||||
|
def childFromName(self) -> Value : ...
|
||||||
|
def childFromField(self) -> Value : ...
|
||||||
|
def childFromIndex(self) -> Value : ...
|
||||||
|
|
||||||
|
def parseAndEvaluate() -> Value : ...
|
||||||
|
def resolveSymbol() -> list[str] : ...
|
||||||
|
def getNameByAddress() -> str : ...
|
||||||
|
def getAddressByName() -> int : ...
|
||||||
|
def lookupType() -> Type | None : ...
|
||||||
|
def listOfLocals() -> list[Value] : ...
|
||||||
|
def listOfModules() -> list[str] : ...
|
||||||
|
def pointerSize() -> int : ...
|
||||||
|
def readRawMemory() -> bytes : ...
|
||||||
|
def createValue() -> Value | None : ...
|
||||||
|
def call() -> Value | None : ...
|
||||||
|
def reportResult() -> None : ...
|
@@ -569,7 +569,7 @@ def qdump__QDir(d, value):
|
|||||||
with SubItem(d, 'absolutePath'):
|
with SubItem(d, 'absolutePath'):
|
||||||
d.putItem(d.createValue(privAddress + absoluteDirEntryOffset, '@QString'))
|
d.putItem(d.createValue(privAddress + absoluteDirEntryOffset, '@QString'))
|
||||||
with SubItem(d, 'entryInfoList'):
|
with SubItem(d, 'entryInfoList'):
|
||||||
qdumpHelper_QList(d, privAddress + fileInfosOffset, '@QFileInfo')
|
qdumpHelper_QList(d, d.createValue(privAddress + fileInfosOffset, '@QList<@QFileInfo>'), '@QFileInfo')
|
||||||
with SubItem(d, 'entryList'):
|
with SubItem(d, 'entryList'):
|
||||||
d.putItem(d.createValue(privAddress + filesOffset, '@QStringList'))
|
d.putItem(d.createValue(privAddress + filesOffset, '@QStringList'))
|
||||||
d.putFields(value)
|
d.putFields(value)
|
||||||
@@ -1256,7 +1256,7 @@ def qdump__QLocale(d, value):
|
|||||||
|
|
||||||
prefix = ns + 'QLocale::'
|
prefix = ns + 'QLocale::'
|
||||||
try:
|
try:
|
||||||
if qtVersionAtLeast(0x060700):
|
if d.qtVersionAtLeast(0x060700):
|
||||||
res = d.call('const char *', value, 'name', prefix + 'TagSeparator::Underscore')
|
res = d.call('const char *', value, 'name', prefix + 'TagSeparator::Underscore')
|
||||||
else:
|
else:
|
||||||
res = d.call('const char *', value, 'name')
|
res = d.call('const char *', value, 'name')
|
||||||
|
@@ -21936,8 +21936,14 @@ Doppelklicken Sie einen Eintrag um ihn zu ändern.</translation>
|
|||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Executable:</source>
|
<source>Executable:</source>
|
||||||
|
<comment>adjective</comment>
|
||||||
<translation>Ausführbar:</translation>
|
<translation>Ausführbar:</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Executable:</source>
|
||||||
|
<comment>noun</comment>
|
||||||
|
<translation>Ausführbare Datei:</translation>
|
||||||
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Symbolic link:</source>
|
<source>Symbolic link:</source>
|
||||||
<translation>Symbolischer Link:</translation>
|
<translation>Symbolischer Link:</translation>
|
||||||
|
@@ -2133,8 +2133,14 @@ Međutim, korištenje opuštenih i proširenih pravila također znači da nije m
|
|||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Executable:</source>
|
<source>Executable:</source>
|
||||||
|
<comment>adjective</comment>
|
||||||
<translation>Izvršavajuća:</translation>
|
<translation>Izvršavajuća:</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Executable:</source>
|
||||||
|
<comment>noun</comment>
|
||||||
|
<translation>Izvršna datoteka:</translation>
|
||||||
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Symbolic link:</source>
|
<source>Symbolic link:</source>
|
||||||
<translation>Simbolička poveznica:</translation>
|
<translation>Simbolička poveznica:</translation>
|
||||||
|
@@ -18313,8 +18313,14 @@ will also disable the following plugins:
|
|||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Executable:</source>
|
<source>Executable:</source>
|
||||||
|
<comment>adjective</comment>
|
||||||
<translation>Можно запускать:</translation>
|
<translation>Можно запускать:</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Executable:</source>
|
||||||
|
<comment>noun</comment>
|
||||||
|
<translation>Программа:</translation>
|
||||||
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Symbolic link:</source>
|
<source>Symbolic link:</source>
|
||||||
<translation>Символьная ссылка:</translation>
|
<translation>Символьная ссылка:</translation>
|
||||||
|
@@ -17,6 +17,7 @@ Product {
|
|||||||
"designer/**/*",
|
"designer/**/*",
|
||||||
"glsl/**/*",
|
"glsl/**/*",
|
||||||
"jsonschemas/**/*",
|
"jsonschemas/**/*",
|
||||||
|
"lua-plugins/**/*",
|
||||||
"modeleditor/**/*",
|
"modeleditor/**/*",
|
||||||
"qml/**/*",
|
"qml/**/*",
|
||||||
"qmldesigner/**/*",
|
"qmldesigner/**/*",
|
||||||
|
@@ -177,8 +177,11 @@ static inline int askMsgSendFailed()
|
|||||||
|
|
||||||
static inline QStringList getPluginPaths()
|
static inline QStringList getPluginPaths()
|
||||||
{
|
{
|
||||||
QStringList rc(QDir::cleanPath(QApplication::applicationDirPath()
|
QStringList rc;
|
||||||
+ '/' + RELATIVE_PLUGIN_PATH));
|
rc << (QDir::cleanPath(QApplication::applicationDirPath()
|
||||||
|
+ '/' + RELATIVE_PLUGIN_PATH))
|
||||||
|
<< (QDir::cleanPath(QApplication::applicationDirPath()
|
||||||
|
+ '/' + RELATIVE_DATA_PATH + "/lua-plugins"));
|
||||||
// Local plugin path: <localappdata>/plugins/<ideversion>
|
// Local plugin path: <localappdata>/plugins/<ideversion>
|
||||||
// where <localappdata> is e.g.
|
// where <localappdata> is e.g.
|
||||||
// "%LOCALAPPDATA%\QtProject\qtcreator" on Windows Vista and later
|
// "%LOCALAPPDATA%\QtProject\qtcreator" on Windows Vista and later
|
||||||
|
@@ -17,9 +17,11 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
|
#include <QFileSystemWatcher>
|
||||||
#include <QOperatingSystemVersion>
|
#include <QOperatingSystemVersion>
|
||||||
#include <QRandomGenerator>
|
#include <QRandomGenerator>
|
||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
|
#include <QStandardPaths>
|
||||||
#include <QStorageInfo>
|
#include <QStorageInfo>
|
||||||
#include <QTemporaryFile>
|
#include <QTemporaryFile>
|
||||||
|
|
||||||
@@ -33,7 +35,6 @@
|
|||||||
#include <qplatformdefs.h>
|
#include <qplatformdefs.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <QStandardPaths>
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <array>
|
#include <array>
|
||||||
|
|
||||||
@@ -389,6 +390,13 @@ expected_str<FilePath> DeviceFileAccess::createTempFile(const FilePath &filePath
|
|||||||
Tr::tr("createTempFile is not implemented for \"%1\".").arg(filePath.toUserOutput()));
|
Tr::tr("createTempFile is not implemented for \"%1\".").arg(filePath.toUserOutput()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Utils::expected_str<std::unique_ptr<FilePathWatcher>> DeviceFileAccess::watch(
|
||||||
|
const FilePath &path) const
|
||||||
|
{
|
||||||
|
Q_UNUSED(path);
|
||||||
|
return make_unexpected(Tr::tr("watch is not implemented."));
|
||||||
|
}
|
||||||
|
|
||||||
// DesktopDeviceFileAccess
|
// DesktopDeviceFileAccess
|
||||||
|
|
||||||
DesktopDeviceFileAccess::~DesktopDeviceFileAccess() = default;
|
DesktopDeviceFileAccess::~DesktopDeviceFileAccess() = default;
|
||||||
@@ -767,6 +775,29 @@ expected_str<FilePath> DesktopDeviceFileAccess::createTempFile(const FilePath &f
|
|||||||
return filePath.withNewPath(file.fileName());
|
return filePath.withNewPath(file.fileName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class DesktopFilePathWatcher : public FilePathWatcher
|
||||||
|
{
|
||||||
|
QFileSystemWatcher m_watcher;
|
||||||
|
|
||||||
|
public:
|
||||||
|
DesktopFilePathWatcher(const FilePath &path) {
|
||||||
|
connect(&m_watcher, &QFileSystemWatcher::fileChanged, this, [this, path] {
|
||||||
|
emit pathChanged(path);
|
||||||
|
});
|
||||||
|
connect(&m_watcher, &QFileSystemWatcher::directoryChanged, this, [this, path] {
|
||||||
|
emit pathChanged(path);
|
||||||
|
});
|
||||||
|
|
||||||
|
m_watcher.addPath(path.path());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Utils::expected_str<std::unique_ptr<FilePathWatcher>> DesktopDeviceFileAccess::watch(
|
||||||
|
const FilePath &path) const
|
||||||
|
{
|
||||||
|
return std::make_unique<DesktopFilePathWatcher>(path);
|
||||||
|
}
|
||||||
|
|
||||||
QDateTime DesktopDeviceFileAccess::lastModified(const FilePath &filePath) const
|
QDateTime DesktopDeviceFileAccess::lastModified(const FilePath &filePath) const
|
||||||
{
|
{
|
||||||
return QFileInfo(filePath.path()).lastModified();
|
return QFileInfo(filePath.path()).lastModified();
|
||||||
|
@@ -72,6 +72,8 @@ protected:
|
|||||||
const QByteArray &data) const;
|
const QByteArray &data) const;
|
||||||
|
|
||||||
virtual expected_str<FilePath> createTempFile(const FilePath &filePath);
|
virtual expected_str<FilePath> createTempFile(const FilePath &filePath);
|
||||||
|
|
||||||
|
virtual Utils::expected_str<std::unique_ptr<FilePathWatcher>> watch(const FilePath &path) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class QTCREATOR_UTILS_EXPORT DesktopDeviceFileAccess : public DeviceFileAccess
|
class QTCREATOR_UTILS_EXPORT DesktopDeviceFileAccess : public DeviceFileAccess
|
||||||
@@ -128,6 +130,7 @@ protected:
|
|||||||
|
|
||||||
expected_str<FilePath> createTempFile(const FilePath &filePath) override;
|
expected_str<FilePath> createTempFile(const FilePath &filePath) override;
|
||||||
|
|
||||||
|
Utils::expected_str<std::unique_ptr<FilePathWatcher>> watch(const FilePath &path) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class QTCREATOR_UTILS_EXPORT UnixDeviceFileAccess : public DeviceFileAccess
|
class QTCREATOR_UTILS_EXPORT UnixDeviceFileAccess : public DeviceFileAccess
|
||||||
|
@@ -313,6 +313,11 @@ bool FilePath::equalsCaseSensitive(const FilePath &other) const
|
|||||||
return equals(*this, other, Qt::CaseSensitive);
|
return equals(*this, other, Qt::CaseSensitive);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Utils::expected_str<std::unique_ptr<FilePathWatcher>> FilePath::watch() const
|
||||||
|
{
|
||||||
|
return fileAccess()->watch(*this);
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Returns a QString for passing on to QString based APIs.
|
Returns a QString for passing on to QString based APIs.
|
||||||
|
|
||||||
|
@@ -55,6 +55,16 @@ public:
|
|||||||
|
|
||||||
using FilePaths = QList<class FilePath>;
|
using FilePaths = QList<class FilePath>;
|
||||||
|
|
||||||
|
class QTCREATOR_UTILS_EXPORT FilePathWatcher : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
using QObject::QObject;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void pathChanged(const Utils::FilePath &path);
|
||||||
|
};
|
||||||
|
|
||||||
class QTCREATOR_UTILS_EXPORT FilePath
|
class QTCREATOR_UTILS_EXPORT FilePath
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -270,6 +280,8 @@ public:
|
|||||||
|
|
||||||
bool equalsCaseSensitive(const FilePath &other) const;
|
bool equalsCaseSensitive(const FilePath &other) const;
|
||||||
|
|
||||||
|
Utils::expected_str<std::unique_ptr<FilePathWatcher>> watch() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// These are needed.
|
// These are needed.
|
||||||
QTCREATOR_UTILS_EXPORT friend bool operator==(const FilePath &first, const FilePath &second);
|
QTCREATOR_UTILS_EXPORT friend bool operator==(const FilePath &first, const FilePath &second);
|
||||||
|
@@ -73,21 +73,14 @@ NameValueItemsWidget::NameValueItemsWidget(QWidget *parent)
|
|||||||
layout->addWidget(m_editor);
|
layout->addWidget(m_editor);
|
||||||
layout->addWidget(new QLabel(helpText, this));
|
layout->addWidget(new QLabel(helpText, this));
|
||||||
|
|
||||||
const auto checkForItemChange = [this] {
|
|
||||||
const EnvironmentItems newItems = environmentItems();
|
|
||||||
if (newItems != m_originalItems) {
|
|
||||||
m_originalItems = newItems;
|
|
||||||
emit userChangedItems(newItems);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const auto timer = new QTimer(this);
|
const auto timer = new QTimer(this);
|
||||||
timer->setSingleShot(true);
|
timer->setSingleShot(true);
|
||||||
timer->setInterval(1000);
|
timer->setInterval(1000);
|
||||||
connect(m_editor, &QPlainTextEdit::textChanged, timer, qOverload<>(&QTimer::start));
|
connect(m_editor, &QPlainTextEdit::textChanged, timer, qOverload<>(&QTimer::start));
|
||||||
connect(timer, &QTimer::timeout, this, checkForItemChange);
|
connect(timer, &QTimer::timeout, this, &NameValueItemsWidget::forceUpdateCheck);
|
||||||
connect(m_editor, &Internal::TextEditHelper::lostFocus, this, [timer, checkForItemChange] {
|
connect(m_editor, &Internal::TextEditHelper::lostFocus, this, [this, timer] {
|
||||||
timer->stop();
|
timer->stop();
|
||||||
checkForItemChange();
|
forceUpdateCheck();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,6 +152,15 @@ bool NameValueItemsWidget::editVariable(const QString &name, Selection selection
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NameValueItemsWidget::forceUpdateCheck()
|
||||||
|
{
|
||||||
|
const EnvironmentItems newItems = environmentItems();
|
||||||
|
if (newItems != m_originalItems) {
|
||||||
|
m_originalItems = newItems;
|
||||||
|
emit userChangedItems(newItems);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
NameValuesDialog::NameValuesDialog(const QString &windowTitle, QWidget *parent)
|
NameValuesDialog::NameValuesDialog(const QString &windowTitle, QWidget *parent)
|
||||||
: QDialog(parent)
|
: QDialog(parent)
|
||||||
{
|
{
|
||||||
|
@@ -29,6 +29,8 @@ public:
|
|||||||
enum class Selection { Name, Value };
|
enum class Selection { Name, Value };
|
||||||
bool editVariable(const QString &name, Selection selection);
|
bool editVariable(const QString &name, Selection selection);
|
||||||
|
|
||||||
|
void forceUpdateCheck();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void userChangedItems(const EnvironmentItems &items);
|
void userChangedItems(const EnvironmentItems &items);
|
||||||
|
|
||||||
|
@@ -57,7 +57,7 @@ inline OsArch osArchFromString(const QString &architecture)
|
|||||||
return OsArchItanium;
|
return OsArchItanium;
|
||||||
if (architecture == QLatin1String("arm"))
|
if (architecture == QLatin1String("arm"))
|
||||||
return OsArchArm;
|
return OsArchArm;
|
||||||
if (architecture == QLatin1String("arm64"))
|
if (architecture == QLatin1String("arm64") || architecture == QLatin1String("aarch64"))
|
||||||
return OsArchArm64;
|
return OsArchArm64;
|
||||||
return OsArchUnknown;
|
return OsArchUnknown;
|
||||||
}
|
}
|
||||||
|
@@ -342,14 +342,14 @@ void PathChooser::setEnvironment(const Environment &env)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FilePath PathChooser::rawFilePath() const
|
FilePath PathChooser::unexpandedFilePath() const
|
||||||
{
|
{
|
||||||
return FilePath::fromUserInput(d->m_lineEdit->text());
|
return FilePath::fromUserInput(d->m_lineEdit->text());
|
||||||
}
|
}
|
||||||
|
|
||||||
FilePath PathChooser::filePath() const
|
FilePath PathChooser::filePath() const
|
||||||
{
|
{
|
||||||
return d->expandedPath(rawFilePath());
|
return d->expandedPath(unexpandedFilePath());
|
||||||
}
|
}
|
||||||
|
|
||||||
FilePath PathChooser::absoluteFilePath() const
|
FilePath PathChooser::absoluteFilePath() const
|
||||||
|
@@ -67,10 +67,10 @@ public:
|
|||||||
bool isValid() const;
|
bool isValid() const;
|
||||||
QString errorMessage() const;
|
QString errorMessage() const;
|
||||||
|
|
||||||
FilePath filePath() const; // Close to what's in the line edit.
|
FilePath filePath() const; // Close to what's in the line edit. Expands macros.
|
||||||
FilePath absoluteFilePath() const; // Relative paths resolved wrt the specified base dir.
|
FilePath absoluteFilePath() const; // Relative paths resolved wrt the specified base dir.
|
||||||
|
|
||||||
FilePath rawFilePath() const; // The raw unexpanded input as FilePath.
|
FilePath unexpandedFilePath() const; // The raw unexpanded input as FilePath.
|
||||||
|
|
||||||
FilePath baseDirectory() const;
|
FilePath baseDirectory() const;
|
||||||
void setBaseDirectory(const FilePath &base);
|
void setBaseDirectory(const FilePath &base);
|
||||||
|
@@ -119,7 +119,3 @@ endif()
|
|||||||
add_subdirectory(qnx)
|
add_subdirectory(qnx)
|
||||||
add_subdirectory(mcusupport)
|
add_subdirectory(mcusupport)
|
||||||
add_subdirectory(qtapplicationmanager)
|
add_subdirectory(qtapplicationmanager)
|
||||||
add_subdirectory(luatests)
|
|
||||||
add_subdirectory(tellajoke)
|
|
||||||
add_subdirectory(luals)
|
|
||||||
add_subdirectory(rustls)
|
|
||||||
|
@@ -140,7 +140,7 @@ AndroidBuildApkWidget::AndroidBuildApkWidget(AndroidBuildApkStep *step)
|
|||||||
keystoreLocationChooser->setPromptDialogFilter(Tr::tr("Keystore files (*.keystore *.jks)"));
|
keystoreLocationChooser->setPromptDialogFilter(Tr::tr("Keystore files (*.keystore *.jks)"));
|
||||||
keystoreLocationChooser->setPromptDialogTitle(Tr::tr("Select Keystore File"));
|
keystoreLocationChooser->setPromptDialogTitle(Tr::tr("Select Keystore File"));
|
||||||
connect(keystoreLocationChooser, &PathChooser::textChanged, this, [this, keystoreLocationChooser] {
|
connect(keystoreLocationChooser, &PathChooser::textChanged, this, [this, keystoreLocationChooser] {
|
||||||
const FilePath file = keystoreLocationChooser->rawFilePath();
|
const FilePath file = keystoreLocationChooser->unexpandedFilePath();
|
||||||
m_step->setKeystorePath(file);
|
m_step->setKeystorePath(file);
|
||||||
m_signPackageCheckBox->setChecked(!file.isEmpty());
|
m_signPackageCheckBox->setChecked(!file.isEmpty());
|
||||||
if (!file.isEmpty())
|
if (!file.isEmpty())
|
||||||
|
@@ -151,7 +151,7 @@ ChooseDirectoryPage::ChooseDirectoryPage(CreateAndroidManifestWizard *wizard)
|
|||||||
m_layout->addRow(m_sourceDirectoryWarning);
|
m_layout->addRow(m_sourceDirectoryWarning);
|
||||||
|
|
||||||
connect(m_androidPackageSourceDir, &PathChooser::textChanged, m_wizard, [this] {
|
connect(m_androidPackageSourceDir, &PathChooser::textChanged, m_wizard, [this] {
|
||||||
m_wizard->setDirectory(m_androidPackageSourceDir->rawFilePath());
|
m_wizard->setDirectory(m_androidPackageSourceDir->unexpandedFilePath());
|
||||||
});
|
});
|
||||||
|
|
||||||
if (wizard->copyGradle()) {
|
if (wizard->copyGradle()) {
|
||||||
|
@@ -20,10 +20,13 @@ using namespace Utils;
|
|||||||
namespace ClangTools {
|
namespace ClangTools {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
|
static TextMarkCategory clangToolsCategory()
|
||||||
|
{
|
||||||
|
return {Tr::tr("Clang Tools"), Id(Constants::DIAGNOSTIC_MARK_ID)};
|
||||||
|
}
|
||||||
|
|
||||||
DiagnosticMark::DiagnosticMark(const Diagnostic &diagnostic, TextDocument *document)
|
DiagnosticMark::DiagnosticMark(const Diagnostic &diagnostic, TextDocument *document)
|
||||||
: TextMark(document,
|
: TextMark(document, diagnostic.location.line, clangToolsCategory())
|
||||||
diagnostic.location.line,
|
|
||||||
{Tr::tr("Clang Tools"), Id(Constants::DIAGNOSTIC_MARK_ID)})
|
|
||||||
, m_diagnostic(diagnostic)
|
, m_diagnostic(diagnostic)
|
||||||
{
|
{
|
||||||
setSettingsPage(Constants::SETTINGS_PAGE_ID);
|
setSettingsPage(Constants::SETTINGS_PAGE_ID);
|
||||||
@@ -60,7 +63,8 @@ DiagnosticMark::DiagnosticMark(const Diagnostic &diagnostic, TextDocument *docum
|
|||||||
}
|
}
|
||||||
|
|
||||||
DiagnosticMark::DiagnosticMark(const Diagnostic &diagnostic)
|
DiagnosticMark::DiagnosticMark(const Diagnostic &diagnostic)
|
||||||
: DiagnosticMark(diagnostic, TextDocument::textDocumentForFilePath(diagnostic.location.filePath))
|
: TextMark(diagnostic.location.filePath, diagnostic.location.line, clangToolsCategory())
|
||||||
|
, m_diagnostic(diagnostic)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void DiagnosticMark::disable()
|
void DiagnosticMark::disable()
|
||||||
|
@@ -99,12 +99,12 @@ SettingsWidget::~SettingsWidget()
|
|||||||
|
|
||||||
FilePath SettingsWidget::clangTidyPath() const
|
FilePath SettingsWidget::clangTidyPath() const
|
||||||
{
|
{
|
||||||
return m_clangTidyPathChooser->rawFilePath();
|
return m_clangTidyPathChooser->unexpandedFilePath();
|
||||||
}
|
}
|
||||||
|
|
||||||
FilePath SettingsWidget::clazyStandalonePath() const
|
FilePath SettingsWidget::clazyStandalonePath() const
|
||||||
{
|
{
|
||||||
return m_clazyStandalonePathChooser->rawFilePath();
|
return m_clazyStandalonePathChooser->unexpandedFilePath();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClangToolsOptionsPage
|
// ClangToolsOptionsPage
|
||||||
|
@@ -177,7 +177,7 @@ SettingsPageWidget::SettingsPageWidget()
|
|||||||
void SettingsPageWidget::apply()
|
void SettingsPageWidget::apply()
|
||||||
{
|
{
|
||||||
ClearCaseSettings rc;
|
ClearCaseSettings rc;
|
||||||
rc.ccCommand = commandPathChooser->rawFilePath().toString();
|
rc.ccCommand = commandPathChooser->unexpandedFilePath().toString();
|
||||||
rc.ccBinaryPath = commandPathChooser->filePath();
|
rc.ccBinaryPath = commandPathChooser->filePath();
|
||||||
rc.timeOutS = timeOutSpinBox->value();
|
rc.timeOutS = timeOutSpinBox->value();
|
||||||
rc.autoCheckOut = autoCheckOutCheckBox->isChecked();
|
rc.autoCheckOut = autoCheckOutCheckBox->isChecked();
|
||||||
|
@@ -985,7 +985,7 @@ bool CMakeBuildSystem::renameFile(Node *context,
|
|||||||
|
|
||||||
// Try the next occurrence. This can happen if set_source_file_properties is used
|
// Try the next occurrence. This can happen if set_source_file_properties is used
|
||||||
fileToRename = projectFileArgumentPosition(targetName, oldRelPathName);
|
fileToRename = projectFileArgumentPosition(targetName, oldRelPathName);
|
||||||
} while (fileToRename);
|
} while (fileToRename && !fileToRename->fromGlobbing);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -1977,6 +1977,9 @@ static FilePaths librarySearchPaths(const CMakeBuildSystem *bs, const QString &b
|
|||||||
|
|
||||||
const QList<BuildTargetInfo> CMakeBuildSystem::appTargets() const
|
const QList<BuildTargetInfo> CMakeBuildSystem::appTargets() const
|
||||||
{
|
{
|
||||||
|
const CMakeConfig &cm = configurationFromCMake();
|
||||||
|
QString emulator = cm.stringValueOf("CMAKE_CROSSCOMPILING_EMULATOR");
|
||||||
|
|
||||||
QList<BuildTargetInfo> appTargetList;
|
QList<BuildTargetInfo> appTargetList;
|
||||||
const bool forAndroid = DeviceTypeKitAspect::deviceTypeId(kit())
|
const bool forAndroid = DeviceTypeKitAspect::deviceTypeId(kit())
|
||||||
== Android::Constants::ANDROID_DEVICE_TYPE;
|
== Android::Constants::ANDROID_DEVICE_TYPE;
|
||||||
@@ -1989,6 +1992,15 @@ const QList<BuildTargetInfo> CMakeBuildSystem::appTargets() const
|
|||||||
|
|
||||||
BuildTargetInfo bti;
|
BuildTargetInfo bti;
|
||||||
bti.displayName = ct.title;
|
bti.displayName = ct.title;
|
||||||
|
if (ct.launchers.size() > 0)
|
||||||
|
bti.launchers = ct.launchers;
|
||||||
|
else if (!emulator.isEmpty()) {
|
||||||
|
// fallback for cmake < 3.29
|
||||||
|
QStringList args = emulator.split(";");
|
||||||
|
FilePath command = FilePath::fromString(args.takeFirst());
|
||||||
|
LauncherInfo launcherInfo = { "emulator", command, args };
|
||||||
|
bti.launchers.append(Launcher(launcherInfo, ct.sourceDirectory));
|
||||||
|
}
|
||||||
bti.targetFilePath = ct.executable;
|
bti.targetFilePath = ct.executable;
|
||||||
bti.projectFilePath = ct.sourceDirectory.cleanPath();
|
bti.projectFilePath = ct.sourceDirectory.cleanPath();
|
||||||
bti.workingDirectory = ct.workingDirectory;
|
bti.workingDirectory = ct.workingDirectory;
|
||||||
|
@@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
#include <projectexplorer/projectmacro.h>
|
#include <projectexplorer/projectmacro.h>
|
||||||
#include <projectexplorer/projectnodes.h>
|
#include <projectexplorer/projectnodes.h>
|
||||||
|
#include <projectexplorer/runconfigurationaspects.h>
|
||||||
|
|
||||||
#include <utils/fileutils.h>
|
#include <utils/fileutils.h>
|
||||||
|
|
||||||
@@ -30,6 +31,7 @@ class CMAKE_EXPORT CMakeBuildTarget
|
|||||||
public:
|
public:
|
||||||
QString title;
|
QString title;
|
||||||
Utils::FilePath executable; // TODO: rename to output?
|
Utils::FilePath executable; // TODO: rename to output?
|
||||||
|
QList<ProjectExplorer::Launcher> launchers;
|
||||||
TargetType targetType = UtilityType;
|
TargetType targetType = UtilityType;
|
||||||
bool linksToQtGui = false;
|
bool linksToQtGui = false;
|
||||||
bool qtcRunnable = true;
|
bool qtcRunnable = true;
|
||||||
|
@@ -94,8 +94,8 @@ void ConfigModelItemDelegate::setModelData(QWidget *editor, QAbstractItemModel *
|
|||||||
ConfigModel::DataItem data = ConfigModel::dataItemFromIndex(index);
|
ConfigModel::DataItem data = ConfigModel::dataItemFromIndex(index);
|
||||||
if (data.type == ConfigModel::DataItem::FILE || data.type == ConfigModel::DataItem::DIRECTORY) {
|
if (data.type == ConfigModel::DataItem::FILE || data.type == ConfigModel::DataItem::DIRECTORY) {
|
||||||
auto edit = static_cast<PathChooser *>(editor);
|
auto edit = static_cast<PathChooser *>(editor);
|
||||||
if (edit->rawFilePath().toString() != data.value)
|
if (edit->unexpandedFilePath().toString() != data.value)
|
||||||
model->setData(index, edit->rawFilePath().toString(), Qt::EditRole);
|
model->setData(index, edit->unexpandedFilePath().toString(), Qt::EditRole);
|
||||||
return;
|
return;
|
||||||
} else if (!data.values.isEmpty()) {
|
} else if (!data.values.isEmpty()) {
|
||||||
auto edit = static_cast<QComboBox *>(editor);
|
auto edit = static_cast<QComboBox *>(editor);
|
||||||
|
@@ -342,6 +342,22 @@ static CMakeBuildTarget toBuildTarget(const TargetDetails &t,
|
|||||||
}
|
}
|
||||||
ct.libraryDirectories = filteredUnique(librarySeachPaths);
|
ct.libraryDirectories = filteredUnique(librarySeachPaths);
|
||||||
qCInfo(cmakeLogger) << "libraryDirectories for target" << ct.title << ":" << ct.libraryDirectories;
|
qCInfo(cmakeLogger) << "libraryDirectories for target" << ct.title << ":" << ct.libraryDirectories;
|
||||||
|
|
||||||
|
// If there are start programs, there should also be an option to select none
|
||||||
|
if (!t.launcherInfos.isEmpty()) {
|
||||||
|
LauncherInfo info { "unused", Utils::FilePath(), QStringList() };
|
||||||
|
ct.launchers.append(Launcher(info, sourceDirectory));
|
||||||
|
}
|
||||||
|
// if there is a test and an emulator launcher, add the emulator and
|
||||||
|
// also a combination as the last entry, but not the "test" launcher
|
||||||
|
// as it will not work for cross-compiled executables
|
||||||
|
if (t.launcherInfos.size() == 2 && t.launcherInfos[0].type == "test" && t.launcherInfos[1].type == "emulator") {
|
||||||
|
ct.launchers.append(Launcher(t.launcherInfos[1], sourceDirectory));
|
||||||
|
ct.launchers.append(Launcher(t.launcherInfos[0], t.launcherInfos[1], sourceDirectory));
|
||||||
|
} else if (t.launcherInfos.size() == 1) {
|
||||||
|
Launcher launcher(t.launcherInfos[0], sourceDirectory);
|
||||||
|
ct.launchers.append(launcher);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return ct;
|
return ct;
|
||||||
}
|
}
|
||||||
|
@@ -11,6 +11,7 @@
|
|||||||
#include <projectexplorer/rawprojectpart.h>
|
#include <projectexplorer/rawprojectpart.h>
|
||||||
|
|
||||||
#include <utils/algorithm.h>
|
#include <utils/algorithm.h>
|
||||||
|
#include <utils/filepath.h>
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
|
|
||||||
#include <QGuiApplication>
|
#include <QGuiApplication>
|
||||||
@@ -650,6 +651,19 @@ static TargetDetails extractTargetDetails(const QJsonObject &root, QString &erro
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
const QJsonArray launchers = root.value("launchers").toArray();
|
||||||
|
if (launchers.size() > 0) {
|
||||||
|
t.launcherInfos = transform<QList>(launchers, [](const QJsonValue &v) {
|
||||||
|
const QJsonObject o = v.toObject();
|
||||||
|
QList<QString> arguments;
|
||||||
|
for (const QJsonValue &arg : o.value("arguments").toArray())
|
||||||
|
arguments.append(arg.toString());
|
||||||
|
FilePath command = FilePath::fromString(o.value("command").toString());
|
||||||
|
return ProjectExplorer::LauncherInfo { o.value("type").toString(), command, arguments };
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
@@ -197,6 +197,7 @@ public:
|
|||||||
QList<Utils::FilePath> artifacts;
|
QList<Utils::FilePath> artifacts;
|
||||||
QString installPrefix;
|
QString installPrefix;
|
||||||
std::vector<InstallDestination> installDestination;
|
std::vector<InstallDestination> installDestination;
|
||||||
|
QList<ProjectExplorer::LauncherInfo> launcherInfos;
|
||||||
std::optional<LinkInfo> link;
|
std::optional<LinkInfo> link;
|
||||||
std::optional<ArchiveInfo> archive;
|
std::optional<ArchiveInfo> archive;
|
||||||
std::vector<DependencyInfo> dependencies;
|
std::vector<DependencyInfo> dependencies;
|
||||||
|
@@ -563,7 +563,7 @@ ExternalToolConfig::ExternalToolConfig()
|
|||||||
|
|
||||||
Form {
|
Form {
|
||||||
Tr::tr("Description:"), m_description, br,
|
Tr::tr("Description:"), m_description, br,
|
||||||
Tr::tr("Executable:"), m_executable, br,
|
Tr::tr("Executable:", "noun"), m_executable, br,
|
||||||
Tr::tr("Arguments:"), m_arguments, br,
|
Tr::tr("Arguments:"), m_arguments, br,
|
||||||
Tr::tr("Working directory:"), m_workingDirectory, br,
|
Tr::tr("Working directory:"), m_workingDirectory, br,
|
||||||
outputLabel, m_outputBehavior, br,
|
outputLabel, m_outputBehavior, br,
|
||||||
@@ -700,12 +700,12 @@ void ExternalToolConfig::updateItem(const QModelIndex &index)
|
|||||||
tool->setDescription(m_description->text());
|
tool->setDescription(m_description->text());
|
||||||
FilePaths executables = tool->executables();
|
FilePaths executables = tool->executables();
|
||||||
if (executables.size() > 0)
|
if (executables.size() > 0)
|
||||||
executables[0] = m_executable->rawFilePath();
|
executables[0] = m_executable->unexpandedFilePath();
|
||||||
else
|
else
|
||||||
executables << m_executable->rawFilePath();
|
executables << m_executable->unexpandedFilePath();
|
||||||
tool->setExecutables(executables);
|
tool->setExecutables(executables);
|
||||||
tool->setArguments(m_arguments->text());
|
tool->setArguments(m_arguments->text());
|
||||||
tool->setWorkingDirectory(m_workingDirectory->rawFilePath());
|
tool->setWorkingDirectory(m_workingDirectory->unexpandedFilePath());
|
||||||
tool->setBaseEnvironmentProviderId(Id::fromSetting(m_baseEnvironment->currentData()));
|
tool->setBaseEnvironmentProviderId(Id::fromSetting(m_baseEnvironment->currentData()));
|
||||||
tool->setEnvironmentUserChanges(m_environment);
|
tool->setEnvironmentUserChanges(m_environment);
|
||||||
tool->setOutputHandling(ExternalTool::OutputHandling(m_outputBehavior->currentIndex()));
|
tool->setOutputHandling(ExternalTool::OutputHandling(m_outputBehavior->currentIndex()));
|
||||||
|
@@ -79,7 +79,7 @@ FilePropertiesDialog::FilePropertiesDialog(const FilePath &filePath, QWidget *pa
|
|||||||
Tr::tr("Last modified:"), m_lastModified, br,
|
Tr::tr("Last modified:"), m_lastModified, br,
|
||||||
Tr::tr("Readable:"), m_readable, br,
|
Tr::tr("Readable:"), m_readable, br,
|
||||||
Tr::tr("Writable:"), m_writable, br,
|
Tr::tr("Writable:"), m_writable, br,
|
||||||
Tr::tr("Executable:"), m_executable, br,
|
Tr::tr("Executable:", "adjective"), m_executable, br,
|
||||||
Tr::tr("Symbolic link:"), m_symLink, br
|
Tr::tr("Symbolic link:"), m_symLink, br
|
||||||
},
|
},
|
||||||
buttonBox
|
buttonBox
|
||||||
|
@@ -220,7 +220,7 @@ bool SpotlightLocatorFilter::openConfigDialog(QWidget *parent, bool &needsRefres
|
|||||||
caseSensitiveArgumentsEdit->setText(m_caseSensitiveArguments);
|
caseSensitiveArgumentsEdit->setText(m_caseSensitiveArguments);
|
||||||
auto sortResults = new QCheckBox(Tr::tr("Sort results"));
|
auto sortResults = new QCheckBox(Tr::tr("Sort results"));
|
||||||
sortResults->setChecked(m_sortResults);
|
sortResults->setChecked(m_sortResults);
|
||||||
layout->addRow(Tr::tr("Executable:"), commandEdit);
|
layout->addRow(Tr::tr("Executable:", "noun"), commandEdit);
|
||||||
layout->addRow(Tr::tr("Arguments:"), argumentsEdit);
|
layout->addRow(Tr::tr("Arguments:"), argumentsEdit);
|
||||||
layout->addRow(Tr::tr("Case sensitive:"), caseSensitiveArgumentsEdit);
|
layout->addRow(Tr::tr("Case sensitive:"), caseSensitiveArgumentsEdit);
|
||||||
layout->addRow({}, sortResults);
|
layout->addRow({}, sortResults);
|
||||||
@@ -231,7 +231,7 @@ bool SpotlightLocatorFilter::openConfigDialog(QWidget *parent, bool &needsRefres
|
|||||||
chooser->addSupportedWidget(caseSensitiveArgumentsEdit);
|
chooser->addSupportedWidget(caseSensitiveArgumentsEdit);
|
||||||
const bool accepted = ILocatorFilter::openConfigDialog(parent, &configWidget);
|
const bool accepted = ILocatorFilter::openConfigDialog(parent, &configWidget);
|
||||||
if (accepted) {
|
if (accepted) {
|
||||||
m_command = commandEdit->rawFilePath().toString();
|
m_command = commandEdit->unexpandedFilePath().toString();
|
||||||
m_arguments = argumentsEdit->text();
|
m_arguments = argumentsEdit->text();
|
||||||
m_caseSensitiveArguments = caseSensitiveArgumentsEdit->text();
|
m_caseSensitiveArguments = caseSensitiveArgumentsEdit->text();
|
||||||
m_sortResults = sortResults->isChecked();
|
m_sortResults = sortResults->isChecked();
|
||||||
|
@@ -239,6 +239,8 @@ void DapClient::emitSignals(const QJsonDocument &doc)
|
|||||||
type = DapResponseType::SetFunctionBreakpoints;
|
type = DapResponseType::SetFunctionBreakpoints;
|
||||||
} else if (command == "attach") {
|
} else if (command == "attach") {
|
||||||
type = DapResponseType::Attach;
|
type = DapResponseType::Attach;
|
||||||
|
} else if (command == "launch") {
|
||||||
|
type = DapResponseType::Launch;
|
||||||
}
|
}
|
||||||
emit responseReady(type, ob);
|
emit responseReady(type, ob);
|
||||||
return;
|
return;
|
||||||
|
@@ -55,6 +55,7 @@ enum class DapResponseType
|
|||||||
SetBreakpoints,
|
SetBreakpoints,
|
||||||
SetFunctionBreakpoints,
|
SetFunctionBreakpoints,
|
||||||
Attach,
|
Attach,
|
||||||
|
Launch,
|
||||||
Unknown
|
Unknown
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -645,6 +645,7 @@ void DapEngine::readDapStandardError()
|
|||||||
void DapEngine::handleResponse(DapResponseType type, const QJsonObject &response)
|
void DapEngine::handleResponse(DapResponseType type, const QJsonObject &response)
|
||||||
{
|
{
|
||||||
const QString command = response.value("command").toString();
|
const QString command = response.value("command").toString();
|
||||||
|
const bool success = response.value("success").toBool();
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case DapResponseType::Initialize:
|
case DapResponseType::Initialize:
|
||||||
@@ -675,7 +676,7 @@ void DapEngine::handleResponse(DapResponseType type, const QJsonObject &response
|
|||||||
case DapResponseType::StepIn:
|
case DapResponseType::StepIn:
|
||||||
case DapResponseType::StepOut:
|
case DapResponseType::StepOut:
|
||||||
case DapResponseType::StepOver:
|
case DapResponseType::StepOver:
|
||||||
if (response.value("success").toBool()) {
|
if (success) {
|
||||||
showMessage(command, LogDebug);
|
showMessage(command, LogDebug);
|
||||||
notifyInferiorRunOk();
|
notifyInferiorRunOk();
|
||||||
} else {
|
} else {
|
||||||
@@ -692,11 +693,21 @@ void DapEngine::handleResponse(DapResponseType type, const QJsonObject &response
|
|||||||
case DapResponseType::SetBreakpoints:
|
case DapResponseType::SetBreakpoints:
|
||||||
handleBreakpointResponse(response);
|
handleBreakpointResponse(response);
|
||||||
break;
|
break;
|
||||||
|
case DapResponseType::Launch:
|
||||||
|
if (!success) {
|
||||||
|
notifyEngineRunFailed();
|
||||||
|
AsynchronousMessageBox::critical(
|
||||||
|
Tr::tr("Failed to Start Application"),
|
||||||
|
Tr::tr("\"%1\" could not be started. Error message: %2")
|
||||||
|
.arg(runParameters().inferior.command.toUserOutput())
|
||||||
|
.arg(response.value("message").toString()));
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
showMessage("UNKNOWN RESPONSE:" + command);
|
showMessage("UNKNOWN RESPONSE:" + command);
|
||||||
};
|
};
|
||||||
|
|
||||||
if (response.contains("success") && !response.value("success").toBool()) {
|
if (!success) {
|
||||||
showMessage(QString("DAP COMMAND FAILED: %1").arg(command));
|
showMessage(QString("DAP COMMAND FAILED: %1").arg(command));
|
||||||
qCDebug(logCategory()) << "DAP COMMAND FAILED:" << command;
|
qCDebug(logCategory()) << "DAP COMMAND FAILED:" << command;
|
||||||
return;
|
return;
|
||||||
|
@@ -115,6 +115,14 @@ LldbDapEngine::LldbDapEngine()
|
|||||||
setDebuggerType("DAP");
|
setDebuggerType("DAP");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QJsonArray LldbDapEngine::environment() const
|
||||||
|
{
|
||||||
|
QJsonArray envArray;
|
||||||
|
for (const QString &value : runParameters().inferior.environment.toDictionary().toStringList())
|
||||||
|
envArray.append(value);
|
||||||
|
return envArray;
|
||||||
|
}
|
||||||
|
|
||||||
QJsonArray LldbDapEngine::sourceMap() const
|
QJsonArray LldbDapEngine::sourceMap() const
|
||||||
{
|
{
|
||||||
QJsonArray sourcePathMapping;
|
QJsonArray sourcePathMapping;
|
||||||
@@ -148,19 +156,25 @@ void LldbDapEngine::handleDapInitialize()
|
|||||||
// * https://github.com/llvm/llvm-project/blob/main/lldb/tools/lldb-dap/package.json
|
// * https://github.com/llvm/llvm-project/blob/main/lldb/tools/lldb-dap/package.json
|
||||||
|
|
||||||
const DebuggerRunParameters &rp = runParameters();
|
const DebuggerRunParameters &rp = runParameters();
|
||||||
|
const QJsonArray map = sourceMap();
|
||||||
|
const QJsonArray commands = preRunCommands();
|
||||||
|
|
||||||
if (!isLocalAttachEngine()) {
|
if (!isLocalAttachEngine()) {
|
||||||
m_dapClient->postRequest(
|
const QJsonArray env = environment();
|
||||||
"launch",
|
QJsonObject launchJson{
|
||||||
QJsonObject{
|
{"noDebug", false},
|
||||||
{"noDebug", false},
|
{"program", rp.inferior.command.executable().path()},
|
||||||
{"program", rp.inferior.command.executable().path()},
|
{"args", rp.inferior.command.arguments()},
|
||||||
{"args", rp.inferior.command.arguments()},
|
{"cwd", rp.inferior.workingDirectory.path()},
|
||||||
{"cwd", rp.inferior.workingDirectory.path()},
|
{"env", env},
|
||||||
{"sourceMap", sourceMap()},
|
{"__restart", ""},
|
||||||
{"preRunCommands", preRunCommands()},
|
};
|
||||||
{"__restart", ""},
|
if (!map.isEmpty())
|
||||||
});
|
launchJson.insert("sourceMap", map);
|
||||||
|
if (!commands.isEmpty())
|
||||||
|
launchJson.insert("preRunCommands", commands);
|
||||||
|
|
||||||
|
m_dapClient->postRequest("launch", launchJson);
|
||||||
|
|
||||||
qCDebug(logCategory()) << "handleDapLaunch";
|
qCDebug(logCategory()) << "handleDapLaunch";
|
||||||
return;
|
return;
|
||||||
@@ -168,15 +182,17 @@ void LldbDapEngine::handleDapInitialize()
|
|||||||
|
|
||||||
QTC_ASSERT(state() == EngineRunRequested, qCDebug(logCategory()) << state());
|
QTC_ASSERT(state() == EngineRunRequested, qCDebug(logCategory()) << state());
|
||||||
|
|
||||||
m_dapClient->postRequest(
|
QJsonObject attachJson{
|
||||||
"attach",
|
{"program", rp.inferior.command.executable().path()},
|
||||||
QJsonObject{
|
{"pid", QString::number(rp.attachPID.pid())},
|
||||||
{"program", rp.inferior.command.executable().path()},
|
{"__restart", ""},
|
||||||
{"pid", QString::number(rp.attachPID.pid())},
|
};
|
||||||
{"sourceMap", sourceMap()},
|
if (!map.isEmpty())
|
||||||
{"preRunCommands", preRunCommands()},
|
attachJson.insert("sourceMap", map);
|
||||||
{"__restart", ""},
|
if (!commands.isEmpty())
|
||||||
});
|
attachJson.insert("preRunCommands", commands);
|
||||||
|
|
||||||
|
m_dapClient->postRequest("attach", attachJson);
|
||||||
|
|
||||||
qCDebug(logCategory()) << "handleDapAttach";
|
qCDebug(logCategory()) << "handleDapAttach";
|
||||||
}
|
}
|
||||||
|
@@ -22,6 +22,7 @@ private:
|
|||||||
bool acceptsBreakpoint(const BreakpointParameters &bp) const override;
|
bool acceptsBreakpoint(const BreakpointParameters &bp) const override;
|
||||||
const QLoggingCategory &logCategory() override;
|
const QLoggingCategory &logCategory() override;
|
||||||
|
|
||||||
|
QJsonArray environment() const;
|
||||||
QJsonArray sourceMap() const;
|
QJsonArray sourceMap() const;
|
||||||
QJsonArray preRunCommands() const;
|
QJsonArray preRunCommands() const;
|
||||||
};
|
};
|
||||||
|
@@ -309,7 +309,7 @@ QString DebuggerSourcePathMappingWidget::editSourceField() const
|
|||||||
|
|
||||||
QString DebuggerSourcePathMappingWidget::editTargetField() const
|
QString DebuggerSourcePathMappingWidget::editTargetField() const
|
||||||
{
|
{
|
||||||
return m_targetChooser->rawFilePath().toString();
|
return m_targetChooser->unexpandedFilePath().toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DebuggerSourcePathMappingWidget::setEditFieldMapping(const Mapping &m)
|
void DebuggerSourcePathMappingWidget::setEditFieldMapping(const Mapping &m)
|
||||||
|
@@ -163,10 +163,10 @@ int AttachCoreDialog::exec()
|
|||||||
{
|
{
|
||||||
connect(d->symbolFileName, &PathChooser::validChanged, this, &AttachCoreDialog::changed);
|
connect(d->symbolFileName, &PathChooser::validChanged, this, &AttachCoreDialog::changed);
|
||||||
connect(d->coreFileName, &PathChooser::validChanged, this, [this] {
|
connect(d->coreFileName, &PathChooser::validChanged, this, [this] {
|
||||||
coreFileChanged(d->coreFileName->rawFilePath());
|
coreFileChanged(d->coreFileName->unexpandedFilePath());
|
||||||
});
|
});
|
||||||
connect(d->coreFileName, &PathChooser::textChanged, this, [this] {
|
connect(d->coreFileName, &PathChooser::textChanged, this, [this] {
|
||||||
coreFileChanged(d->coreFileName->rawFilePath());
|
coreFileChanged(d->coreFileName->unexpandedFilePath());
|
||||||
});
|
});
|
||||||
connect(d->kitChooser, &KitChooser::currentIndexChanged, this, &AttachCoreDialog::changed);
|
connect(d->kitChooser, &KitChooser::currentIndexChanged, this, &AttachCoreDialog::changed);
|
||||||
connect(d->buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
connect(d->buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
||||||
|
@@ -54,6 +54,26 @@ bool DockerApi::canConnect()
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool DockerApi::isContainerRunning(const QString &containerId)
|
||||||
|
{
|
||||||
|
Process process;
|
||||||
|
FilePath dockerExe = dockerClient();
|
||||||
|
if (dockerExe.isEmpty() || !dockerExe.isExecutableFile())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
process.setCommand(
|
||||||
|
CommandLine(dockerExe, QStringList{"inspect", "--format", "{{.State.Running}}", containerId}));
|
||||||
|
process.runBlocking();
|
||||||
|
|
||||||
|
if (process.result() == ProcessResult::FinishedWithSuccess) {
|
||||||
|
QString output = process.readAllStandardOutput().trimmed();
|
||||||
|
if (output == "true")
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void DockerApi::checkCanConnect(bool async)
|
void DockerApi::checkCanConnect(bool async)
|
||||||
{
|
{
|
||||||
if (async) {
|
if (async) {
|
||||||
|
@@ -44,6 +44,8 @@ public:
|
|||||||
static void recheckDockerDaemon();
|
static void recheckDockerDaemon();
|
||||||
QFuture<Utils::expected_str<QList<Network>>> networks();
|
QFuture<Utils::expected_str<QList<Network>>> networks();
|
||||||
|
|
||||||
|
bool isContainerRunning(const QString &containerId);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void dockerDaemonAvailableChanged();
|
void dockerDaemonAvailableChanged();
|
||||||
|
|
||||||
|
@@ -90,7 +90,7 @@ public:
|
|||||||
&Utils::PathChooser::textChanged,
|
&Utils::PathChooser::textChanged,
|
||||||
bc,
|
bc,
|
||||||
[bc, buildDirectoryInput](const QString &) {
|
[bc, buildDirectoryInput](const QString &) {
|
||||||
bc->setBuildDirectory(buildDirectoryInput->rawFilePath());
|
bc->setBuildDirectory(buildDirectoryInput->unexpandedFilePath());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@@ -132,7 +132,7 @@ void CommandBuilderAspect::addToLayout(Layouting::Layout &parent)
|
|||||||
d->makePathChooser->setBaseDirectory(PathChooser::homePath());
|
d->makePathChooser->setBaseDirectory(PathChooser::homePath());
|
||||||
d->makePathChooser->setHistoryCompleter("IncrediBuild.BuildConsole.MakeCommand.History");
|
d->makePathChooser->setHistoryCompleter("IncrediBuild.BuildConsole.MakeCommand.History");
|
||||||
connect(d->makePathChooser, &PathChooser::rawPathChanged, this, [this] {
|
connect(d->makePathChooser, &PathChooser::rawPathChanged, this, [this] {
|
||||||
d->m_activeCommandBuilder->setCommand(d->makePathChooser->rawFilePath());
|
d->m_activeCommandBuilder->setCommand(d->makePathChooser->unexpandedFilePath());
|
||||||
updateGui();
|
updateGui();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@@ -82,6 +82,13 @@ QtcPlugin {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Group {
|
||||||
|
name: "Lua images rcc"
|
||||||
|
Qt.core.resourcePrefix: "lua/images/"
|
||||||
|
fileTags: "qt.core.resource_data"
|
||||||
|
files: "images/**"
|
||||||
|
}
|
||||||
|
|
||||||
Export {
|
Export {
|
||||||
Depends { name: "sol2" }
|
Depends { name: "sol2" }
|
||||||
Depends { name: "lua546" }
|
Depends { name: "lua546" }
|
||||||
|
@@ -373,11 +373,9 @@ QJsonValue LuaEngine::toJson(const sol::table &table)
|
|||||||
QStringList LuaEngine::variadicToStringList(const sol::variadic_args &vargs)
|
QStringList LuaEngine::variadicToStringList(const sol::variadic_args &vargs)
|
||||||
{
|
{
|
||||||
QStringList strings;
|
QStringList strings;
|
||||||
int n = vargs.size();
|
for (size_t i = 1, n = vargs.size(); i <= n; i++) {
|
||||||
int i;
|
|
||||||
for (i = 1; i <= n; i++) {
|
|
||||||
size_t l;
|
size_t l;
|
||||||
const char *s = luaL_tolstring(vargs.lua_state(), i, &l);
|
const char *s = luaL_tolstring(vargs.lua_state(), int(i), &l);
|
||||||
if (s != nullptr)
|
if (s != nullptr)
|
||||||
strings.append(QString::fromUtf8(s, l));
|
strings.append(QString::fromUtf8(s, l));
|
||||||
}
|
}
|
||||||
|
@@ -51,7 +51,7 @@ protected:
|
|||||||
public:
|
public:
|
||||||
using PackageProvider = std::function<sol::object(sol::state_view)>;
|
using PackageProvider = std::function<sol::object(sol::state_view)>;
|
||||||
|
|
||||||
~LuaEngine();
|
~LuaEngine() override;
|
||||||
static LuaEngine &instance();
|
static LuaEngine &instance();
|
||||||
|
|
||||||
Utils::expected_str<LuaPluginSpec *> loadPlugin(const Utils::FilePath &path);
|
Utils::expected_str<LuaPluginSpec *> loadPlugin(const Utils::FilePath &path);
|
||||||
|
@@ -144,14 +144,11 @@ bool LuaPluginSpec::delayedInitialize()
|
|||||||
}
|
}
|
||||||
ExtensionSystem::IPlugin::ShutdownFlag LuaPluginSpec::stop()
|
ExtensionSystem::IPlugin::ShutdownFlag LuaPluginSpec::stop()
|
||||||
{
|
{
|
||||||
d->activeLuaState.reset();
|
d->activeLuaState->stack_clear();
|
||||||
return ExtensionSystem::IPlugin::ShutdownFlag::SynchronousShutdown;
|
return ExtensionSystem::IPlugin::ShutdownFlag::SynchronousShutdown;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LuaPluginSpec::kill()
|
void LuaPluginSpec::kill() {}
|
||||||
{
|
|
||||||
d->activeLuaState.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool LuaPluginSpec::printToOutputPane() const
|
bool LuaPluginSpec::printToOutputPane() const
|
||||||
{
|
{
|
||||||
|
BIN
src/plugins/lua/wizards/plugin/icon.png
Normal file
After Width: | Height: | Size: 887 B |
BIN
src/plugins/lua/wizards/plugin/icon@2x.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
@@ -8,7 +8,8 @@
|
|||||||
"trDescription": "Creates a custom Qt Creator Lua plugin.",
|
"trDescription": "Creates a custom Qt Creator Lua plugin.",
|
||||||
"trDisplayName": "Qt Creator Lua Plugin",
|
"trDisplayName": "Qt Creator Lua Plugin",
|
||||||
"trDisplayCategory": "Library",
|
"trDisplayCategory": "Library",
|
||||||
"iconText": "LuaP",
|
"icon": "icon.png",
|
||||||
|
"iconKind": "Themed",
|
||||||
"featuresRequired": [],
|
"featuresRequired": [],
|
||||||
"options": [
|
"options": [
|
||||||
{
|
{
|
||||||
|
@@ -7,5 +7,7 @@
|
|||||||
<file>plugin/project.json</file>
|
<file>plugin/project.json</file>
|
||||||
<file>plugin/wizard.json</file>
|
<file>plugin/wizard.json</file>
|
||||||
<file>plugin/.luarc.json</file>
|
<file>plugin/.luarc.json</file>
|
||||||
|
<file>plugin/icon.png</file>
|
||||||
|
<file>plugin/icon@2x.png</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
@@ -1,4 +0,0 @@
|
|||||||
add_qtc_lua_plugin(luals
|
|
||||||
SOURCES luals/luals.lua
|
|
||||||
luals/init.lua
|
|
||||||
)
|
|
@@ -1,8 +0,0 @@
|
|||||||
QtcLuaPlugin {
|
|
||||||
name: "luals"
|
|
||||||
|
|
||||||
luafiles: [
|
|
||||||
"init.lua",
|
|
||||||
"luals.lua",
|
|
||||||
]
|
|
||||||
}
|
|
@@ -1,11 +0,0 @@
|
|||||||
add_qtc_lua_plugin(luatests
|
|
||||||
SOURCES
|
|
||||||
luatests/luatests.lua
|
|
||||||
luatests/tests.lua
|
|
||||||
luatests/inspect.lua
|
|
||||||
luatests/qtctest.lua
|
|
||||||
luatests/tst_aspectcontainer.lua
|
|
||||||
luatests/tst_fetch.lua
|
|
||||||
luatests/tst_utils.lua
|
|
||||||
luatests/guidemo.lua
|
|
||||||
)
|
|
@@ -1,14 +0,0 @@
|
|||||||
QtcLuaPlugin {
|
|
||||||
name: "luatests"
|
|
||||||
|
|
||||||
luafiles: [
|
|
||||||
"inspect.lua",
|
|
||||||
"guidemo.lua",
|
|
||||||
"luatests.lua",
|
|
||||||
"qtctest.lua",
|
|
||||||
"tests.lua",
|
|
||||||
"tst_aspectcontainer.lua",
|
|
||||||
"tst_fetch.lua",
|
|
||||||
"tst_utils.lua",
|
|
||||||
]
|
|
||||||
}
|
|
@@ -314,7 +314,7 @@ QWidget *McuPackage::widget()
|
|||||||
QObject::connect(this, &McuPackage::statusChanged, widget, [this] { updateStatusUi(); });
|
QObject::connect(this, &McuPackage::statusChanged, widget, [this] { updateStatusUi(); });
|
||||||
|
|
||||||
QObject::connect(m_fileChooser, &PathChooser::textChanged, this, [this] {
|
QObject::connect(m_fileChooser, &PathChooser::textChanged, this, [this] {
|
||||||
setPath(m_fileChooser->rawFilePath());
|
setPath(m_fileChooser->unexpandedFilePath());
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(this, &McuPackage::changed, m_fileChooser, [this] {
|
connect(this, &McuPackage::changed, m_fileChooser, [this] {
|
||||||
|
@@ -141,7 +141,7 @@ public:
|
|||||||
|
|
||||||
// Connect
|
// Connect
|
||||||
connect(m_compilerCommand, &PathChooser::validChanged, this, [this] {
|
connect(m_compilerCommand, &PathChooser::validChanged, this, [this] {
|
||||||
const FilePath path = m_compilerCommand->rawFilePath();
|
const FilePath path = m_compilerCommand->unexpandedFilePath();
|
||||||
auto tc = static_cast<NimToolchain *>(toolchain());
|
auto tc = static_cast<NimToolchain *>(toolchain());
|
||||||
QTC_ASSERT(tc, return);
|
QTC_ASSERT(tc, return);
|
||||||
tc->setCompilerCommand(path);
|
tc->setCompilerCommand(path);
|
||||||
|
@@ -55,8 +55,6 @@ Project {
|
|||||||
"languageclient/languageclient.qbs",
|
"languageclient/languageclient.qbs",
|
||||||
"languageclient/lualanguageclient/lualanguageclient.qbs",
|
"languageclient/lualanguageclient/lualanguageclient.qbs",
|
||||||
"lua/lua.qbs",
|
"lua/lua.qbs",
|
||||||
"luals/luals.qbs",
|
|
||||||
"luatests/luatests.qbs",
|
|
||||||
"macros/macros.qbs",
|
"macros/macros.qbs",
|
||||||
"marketplace/marketplace.qbs",
|
"marketplace/marketplace.qbs",
|
||||||
"mcusupport/mcusupport.qbs",
|
"mcusupport/mcusupport.qbs",
|
||||||
@@ -81,7 +79,6 @@ Project {
|
|||||||
"qtsupport/qtsupport.qbs",
|
"qtsupport/qtsupport.qbs",
|
||||||
"remotelinux/remotelinux.qbs",
|
"remotelinux/remotelinux.qbs",
|
||||||
"resourceeditor/resourceeditor.qbs",
|
"resourceeditor/resourceeditor.qbs",
|
||||||
"rustls/rustls.qbs",
|
|
||||||
"saferenderer/saferenderer.qbs",
|
"saferenderer/saferenderer.qbs",
|
||||||
"screenrecorder/screenrecorder.qbs",
|
"screenrecorder/screenrecorder.qbs",
|
||||||
"scxmleditor/scxmleditor.qbs",
|
"scxmleditor/scxmleditor.qbs",
|
||||||
@@ -90,7 +87,6 @@ Project {
|
|||||||
"squish/squish.qbs",
|
"squish/squish.qbs",
|
||||||
"studiowelcome/studiowelcome.qbs",
|
"studiowelcome/studiowelcome.qbs",
|
||||||
"subversion/subversion.qbs",
|
"subversion/subversion.qbs",
|
||||||
"tellajoke/tellajoke.qbs",
|
|
||||||
"terminal/terminal.qbs",
|
"terminal/terminal.qbs",
|
||||||
"texteditor/texteditor.qbs",
|
"texteditor/texteditor.qbs",
|
||||||
"todo/todo.qbs",
|
"todo/todo.qbs",
|
||||||
|
@@ -5,12 +5,15 @@
|
|||||||
|
|
||||||
#include "projectexplorer_export.h"
|
#include "projectexplorer_export.h"
|
||||||
|
|
||||||
|
#include "runconfiguration.h"
|
||||||
|
|
||||||
#include <utils/environment.h>
|
#include <utils/environment.h>
|
||||||
#include <utils/filepath.h>
|
#include <utils/filepath.h>
|
||||||
|
|
||||||
#include <QList>
|
#include <QList>
|
||||||
|
|
||||||
namespace ProjectExplorer {
|
namespace ProjectExplorer {
|
||||||
|
class Launcher;
|
||||||
|
|
||||||
class PROJECTEXPLORER_EXPORT BuildTargetInfo
|
class PROJECTEXPLORER_EXPORT BuildTargetInfo
|
||||||
{
|
{
|
||||||
@@ -19,6 +22,7 @@ public:
|
|||||||
QString displayName;
|
QString displayName;
|
||||||
QString displayNameUniquifier;
|
QString displayNameUniquifier;
|
||||||
|
|
||||||
|
QList<Launcher> launchers;
|
||||||
Utils::FilePath targetFilePath;
|
Utils::FilePath targetFilePath;
|
||||||
Utils::FilePath projectFilePath;
|
Utils::FilePath projectFilePath;
|
||||||
Utils::FilePath workingDirectory;
|
Utils::FilePath workingDirectory;
|
||||||
|
@@ -70,6 +70,7 @@ private:
|
|||||||
FilePath executableToRun(const BuildTargetInfo &targetInfo) const;
|
FilePath executableToRun(const BuildTargetInfo &targetInfo) const;
|
||||||
|
|
||||||
const Kind m_kind;
|
const Kind m_kind;
|
||||||
|
LauncherAspect launcher{this};
|
||||||
EnvironmentAspect environment{this};
|
EnvironmentAspect environment{this};
|
||||||
ExecutableAspect executable{this};
|
ExecutableAspect executable{this};
|
||||||
ArgumentsAspect arguments{this};
|
ArgumentsAspect arguments{this};
|
||||||
@@ -90,6 +91,8 @@ void DesktopRunConfiguration::updateTargetInformation()
|
|||||||
auto terminalAspect = aspect<TerminalAspect>();
|
auto terminalAspect = aspect<TerminalAspect>();
|
||||||
terminalAspect->setUseTerminalHint(bti.targetFilePath.needsDevice() ? false : bti.usesTerminal);
|
terminalAspect->setUseTerminalHint(bti.targetFilePath.needsDevice() ? false : bti.usesTerminal);
|
||||||
terminalAspect->setEnabled(!bti.targetFilePath.needsDevice());
|
terminalAspect->setEnabled(!bti.targetFilePath.needsDevice());
|
||||||
|
auto launcherAspect = aspect<LauncherAspect>();
|
||||||
|
launcherAspect->setVisible(false);
|
||||||
|
|
||||||
if (m_kind == Qmake) {
|
if (m_kind == Qmake) {
|
||||||
|
|
||||||
@@ -121,6 +124,12 @@ void DesktopRunConfiguration::updateTargetInformation()
|
|||||||
|
|
||||||
} else if (m_kind == CMake) {
|
} else if (m_kind == CMake) {
|
||||||
|
|
||||||
|
if (bti.launchers.size() > 0) {
|
||||||
|
launcherAspect->setVisible(true);
|
||||||
|
// Use start program by default, if defined (see toBuildTarget() for details)
|
||||||
|
launcherAspect->setDefaultLauncher(bti.launchers.last());
|
||||||
|
launcherAspect->updateLaunchers(bti.launchers);
|
||||||
|
}
|
||||||
aspect<ExecutableAspect>()->setExecutable(bti.targetFilePath);
|
aspect<ExecutableAspect>()->setExecutable(bti.targetFilePath);
|
||||||
aspect<WorkingDirectoryAspect>()->setDefaultWorkingDirectory(bti.workingDirectory);
|
aspect<WorkingDirectoryAspect>()->setDefaultWorkingDirectory(bti.workingDirectory);
|
||||||
emit aspect<EnvironmentAspect>()->environmentChanged();
|
emit aspect<EnvironmentAspect>()->environmentChanged();
|
||||||
|
@@ -139,6 +139,7 @@ public:
|
|||||||
IDevice::MachineType machineType = IDevice::Hardware;
|
IDevice::MachineType machineType = IDevice::Hardware;
|
||||||
OsType osType = OsTypeOther;
|
OsType osType = OsTypeOther;
|
||||||
DeviceFileAccess *fileAccess = nullptr;
|
DeviceFileAccess *fileAccess = nullptr;
|
||||||
|
std::function<DeviceFileAccess *()> fileAccessFactory;
|
||||||
int version = 0; // This is used by devices that have been added by the SDK.
|
int version = 0; // This is used by devices that have been added by the SDK.
|
||||||
|
|
||||||
Utils::SynchronizedValue<SshParameters> sshParameters;
|
Utils::SynchronizedValue<SshParameters> sshParameters;
|
||||||
@@ -251,6 +252,9 @@ bool IDevice::isAnyUnixDevice() const
|
|||||||
|
|
||||||
DeviceFileAccess *IDevice::fileAccess() const
|
DeviceFileAccess *IDevice::fileAccess() const
|
||||||
{
|
{
|
||||||
|
if (d->fileAccessFactory)
|
||||||
|
return d->fileAccessFactory();
|
||||||
|
|
||||||
return d->fileAccess;
|
return d->fileAccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -341,6 +345,11 @@ void IDevice::setFileAccess(DeviceFileAccess *fileAccess)
|
|||||||
d->fileAccess = fileAccess;
|
d->fileAccess = fileAccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IDevice::setFileAccess(std::function<Utils::DeviceFileAccess *()> fileAccessFactory)
|
||||||
|
{
|
||||||
|
d->fileAccessFactory = fileAccessFactory;
|
||||||
|
}
|
||||||
|
|
||||||
IDevice::DeviceInfo IDevice::deviceInformation() const
|
IDevice::DeviceInfo IDevice::deviceInformation() const
|
||||||
{
|
{
|
||||||
const QString key = Tr::tr("Device");
|
const QString key = Tr::tr("Device");
|
||||||
|
@@ -241,6 +241,7 @@ protected:
|
|||||||
void setDisplayType(const QString &type);
|
void setDisplayType(const QString &type);
|
||||||
void setOsType(Utils::OsType osType);
|
void setOsType(Utils::OsType osType);
|
||||||
void setFileAccess(Utils::DeviceFileAccess *fileAccess);
|
void setFileAccess(Utils::DeviceFileAccess *fileAccess);
|
||||||
|
void setFileAccess(std::function<Utils::DeviceFileAccess *()> fileAccessFactory);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
IDevice(const IDevice &) = delete;
|
IDevice(const IDevice &) = delete;
|
||||||
|
@@ -69,7 +69,7 @@ void EnvironmentAspect::setUserEnvironmentChanges(const Utils::EnvironmentItems
|
|||||||
Utils::Environment EnvironmentAspect::environment() const
|
Utils::Environment EnvironmentAspect::environment() const
|
||||||
{
|
{
|
||||||
Environment env = modifiedBaseEnvironment();
|
Environment env = modifiedBaseEnvironment();
|
||||||
env.modify(m_userChanges);
|
env.modify(userEnvironmentChanges());
|
||||||
return env;
|
return env;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -165,4 +165,9 @@ Environment EnvironmentAspect::BaseEnvironment::unmodifiedBaseEnvironment() cons
|
|||||||
return getter ? getter() : Environment();
|
return getter ? getter() : Environment();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Utils::EnvironmentItems EnvironmentAspect::userEnvironmentChanges() const
|
||||||
|
{
|
||||||
|
emit userChangesUpdateRequested();
|
||||||
|
return m_userChanges;
|
||||||
|
}
|
||||||
} // namespace ProjectExplorer
|
} // namespace ProjectExplorer
|
||||||
|
@@ -32,7 +32,7 @@ public:
|
|||||||
int baseEnvironmentBase() const;
|
int baseEnvironmentBase() const;
|
||||||
void setBaseEnvironmentBase(int base);
|
void setBaseEnvironmentBase(int base);
|
||||||
|
|
||||||
Utils::EnvironmentItems userEnvironmentChanges() const { return m_userChanges; }
|
Utils::EnvironmentItems userEnvironmentChanges() const;
|
||||||
void setUserEnvironmentChanges(const Utils::EnvironmentItems &diff);
|
void setUserEnvironmentChanges(const Utils::EnvironmentItems &diff);
|
||||||
|
|
||||||
int addSupportedBaseEnvironment(const QString &displayName,
|
int addSupportedBaseEnvironment(const QString &displayName,
|
||||||
@@ -68,6 +68,7 @@ signals:
|
|||||||
void baseEnvironmentChanged();
|
void baseEnvironmentChanged();
|
||||||
void userEnvironmentChangesChanged(const Utils::EnvironmentItems &diff);
|
void userEnvironmentChangesChanged(const Utils::EnvironmentItems &diff);
|
||||||
void environmentChanged();
|
void environmentChanged();
|
||||||
|
void userChangesUpdateRequested() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void fromMap(const Utils::Store &map) override;
|
void fromMap(const Utils::Store &map) override;
|
||||||
|
@@ -26,6 +26,10 @@ EnvironmentAspectWidget::EnvironmentAspectWidget(EnvironmentAspect *aspect)
|
|||||||
{
|
{
|
||||||
QTC_CHECK(m_aspect);
|
QTC_CHECK(m_aspect);
|
||||||
|
|
||||||
|
connect(m_aspect, &EnvironmentAspect::userChangesUpdateRequested, this, [this] {
|
||||||
|
m_environmentWidget->forceUpdateCheck();
|
||||||
|
});
|
||||||
|
|
||||||
setContentsMargins(0, 0, 0, 0);
|
setContentsMargins(0, 0, 0, 0);
|
||||||
auto topLayout = new QVBoxLayout(this);
|
auto topLayout = new QVBoxLayout(this);
|
||||||
topLayout->setContentsMargins(0, 0, 0, 25);
|
topLayout->setContentsMargins(0, 0, 0, 25);
|
||||||
|
@@ -332,6 +332,7 @@ void EnvironmentWidget::setBaseEnvironmentText(const QString &text)
|
|||||||
|
|
||||||
Utils::EnvironmentItems EnvironmentWidget::userChanges() const
|
Utils::EnvironmentItems EnvironmentWidget::userChanges() const
|
||||||
{
|
{
|
||||||
|
forceUpdateCheck();
|
||||||
return d->m_model->userChanges();
|
return d->m_model->userChanges();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -352,6 +353,11 @@ void EnvironmentWidget::expand()
|
|||||||
d->m_detailsContainer->setState(Utils::DetailsWidget::Expanded);
|
d->m_detailsContainer->setState(Utils::DetailsWidget::Expanded);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EnvironmentWidget::forceUpdateCheck() const
|
||||||
|
{
|
||||||
|
d->m_editor.forceUpdateCheck();
|
||||||
|
}
|
||||||
|
|
||||||
void EnvironmentWidget::updateSummaryText()
|
void EnvironmentWidget::updateSummaryText()
|
||||||
{
|
{
|
||||||
// The summary is redundant with the text edit, so we hide it on expansion.
|
// The summary is redundant with the text edit, so we hide it on expansion.
|
||||||
|
@@ -38,6 +38,8 @@ public:
|
|||||||
|
|
||||||
void expand();
|
void expand();
|
||||||
|
|
||||||
|
void forceUpdateCheck() const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void userChangesChanged();
|
void userChangesChanged();
|
||||||
void detailsVisibleChanged(bool visible);
|
void detailsVisibleChanged(bool visible);
|
||||||
|