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
|
||||
)
|
||||
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
|
||||
--------
|
||||
|
||||
* Added the option to hide all unconfigured kits from the list in `Projects`
|
||||
mode
|
||||
* Added the `Hide Inactive Kits`/`Show All Kits` button to hide inactive kits
|
||||
from the list in the `Projects` mode
|
||||
* 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
|
||||
([QTCREATORBUG-30774](https://bugreports.qt.io/browse/QTCREATORBUG-30774))
|
||||
* Fixed that the column information was not used when opening files from links
|
||||
@@ -148,7 +149,7 @@ Projects
|
||||
|
||||
* Made CMake settings configurable per project
|
||||
* 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))
|
||||
* Fixed that the package manager auto-setup files were not removed with
|
||||
`Clear CMake Configuration`
|
||||
@@ -162,7 +163,11 @@ Projects
|
||||
[QTCREATORBUG-29559](https://bugreports.qt.io/browse/QTCREATORBUG-29559),
|
||||
[QTCREATORBUG-30385](https://bugreports.qt.io/browse/QTCREATORBUG-30385))
|
||||
* Made it possible to register debuggers
|
||||
([QTCREATORBUG-30836](https://bugreports.qt.io/browse/QTCREATORBUG-30836))
|
||||
* 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
|
||||
|
||||
|
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 |
@@ -58,11 +58,25 @@
|
||||
"environment": {
|
||||
"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
|
||||
|
||||
For more information about the CMake project settings in the \c vendor
|
||||
section, see \l {Override CMake settings for a project}.
|
||||
|
||||
\section1 MinGW Example
|
||||
|
||||
The following example configures a Qt project with:
|
||||
@@ -74,6 +88,7 @@
|
||||
\li generator – MinGW Makefiles
|
||||
\li path to a CMake executable
|
||||
\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
|
||||
|
||||
\badcode
|
||||
@@ -92,6 +107,15 @@
|
||||
},
|
||||
"environment": {
|
||||
"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"
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -188,6 +212,50 @@
|
||||
}
|
||||
\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
|
||||
|
||||
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.
|
||||
\QC automatically runs CMake to refresh project information in the
|
||||
view when you edit a \c CMakeLists.txt configuration file
|
||||
in a project. Project information is also automatically refreshed when
|
||||
you build the project.
|
||||
in a project. Also, refreshes project information when you build the project.
|
||||
|
||||
\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
|
||||
location of the file and the contents of the Conan install command.
|
||||
|
||||
Alternatively, you can automatically set up the Conan package manager for
|
||||
use with CMake.
|
||||
\section1 Automatic Package Manager Setup
|
||||
|
||||
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},
|
||||
{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
|
||||
\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}
|
||||
|
||||
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{Specify clangd settings}{Clangd}
|
||||
\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{Configure C++ code model}{C++ Code Model}
|
||||
\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,
|
||||
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
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
@@ -72,5 +73,38 @@
|
||||
a permanent sticky setting that was created just because you wanted to try
|
||||
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}
|
||||
*/
|
||||
|
@@ -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",
|
||||
"QtParts": ["tools"],
|
||||
"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.",
|
||||
"Homepage": "https://github.com/kikito/inspect.lua",
|
||||
"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"
|
||||
}
|
||||
]
|
||||
|
@@ -4,6 +4,7 @@ set(resource_directories
|
||||
glsl
|
||||
indexer_preincludes
|
||||
jsonschemas
|
||||
lua-plugins
|
||||
modeleditor
|
||||
qmldesigner
|
||||
qmlicons
|
||||
@@ -19,6 +20,7 @@ set(resource_files
|
||||
debugger/.pylintrc
|
||||
debugger/boosttypes.py
|
||||
debugger/cdbbridge.py
|
||||
debugger/cdbext.pyi
|
||||
debugger/creatortypes.py
|
||||
debugger/dumper.py
|
||||
debugger/gdbbridge.py
|
||||
|
@@ -85,12 +85,12 @@ class Dumper(DumperBase):
|
||||
del self.type_size_cache[typeid]
|
||||
del self.type_alignment_cache[typeid]
|
||||
|
||||
def enumValue(self, nativeValue):
|
||||
def enumValue(self, nativeValue: cdbext.Value) -> str:
|
||||
val = nativeValue.nativeDebuggerValue()
|
||||
# remove '0n' decimal prefix of the native cdb value output
|
||||
return val.replace('(0n', '(')
|
||||
|
||||
def fromNativeValue(self, nativeValue):
|
||||
def fromNativeValue(self, nativeValue: cdbext.Value) -> DumperBase.Value:
|
||||
self.check(isinstance(nativeValue, cdbext.Value))
|
||||
val = self.Value(self)
|
||||
val.name = nativeValue.name()
|
||||
@@ -133,7 +133,7 @@ class Dumper(DumperBase):
|
||||
val.lbitsize = nativeValue.bitsize()
|
||||
return val
|
||||
|
||||
def nativeTypeId(self, nativeType):
|
||||
def nativeTypeId(self, nativeType: cdbext.Type) -> str:
|
||||
self.check(isinstance(nativeType, cdbext.Type))
|
||||
name = nativeType.name()
|
||||
if name is None or len(name) == 0:
|
||||
@@ -148,7 +148,7 @@ class Dumper(DumperBase):
|
||||
for f in nativeType.fields()])
|
||||
return typeId
|
||||
|
||||
def from_native_type(self, nativeType):
|
||||
def from_native_type(self, nativeType: cdbext.Type) -> str:
|
||||
self.check(isinstance(nativeType, cdbext.Type))
|
||||
typeid = self.typeid_for_string(self.nativeTypeId(nativeType))
|
||||
self.type_nativetype_cache[typeid] = nativeType
|
||||
@@ -187,7 +187,7 @@ class Dumper(DumperBase):
|
||||
self.nativeTypeEnumDisplay(nativeType, intval, form)
|
||||
return typeid
|
||||
|
||||
def listNativeValueChildren(self, nativeValue, include_bases):
|
||||
def listNativeValueChildren(self, nativeValue: cdbext.Value, include_bases: bool) -> list[DumperBase.Value]:
|
||||
fields = []
|
||||
index = 0
|
||||
nativeMember = nativeValue.childFromIndex(index)
|
||||
@@ -202,19 +202,19 @@ class Dumper(DumperBase):
|
||||
nativeMember = nativeValue.childFromIndex(index)
|
||||
return fields
|
||||
|
||||
def listValueChildren(self, value, include_bases=True):
|
||||
def listValueChildren(self, value: DumperBase.Value, include_bases=True) -> list[DumperBase.Value]:
|
||||
nativeValue = value.nativeValue
|
||||
if nativeValue is None:
|
||||
nativeValue = cdbext.createValue(value.address(), self.lookupNativeType(value.type.name, 0))
|
||||
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
|
||||
if nativeValue is None:
|
||||
nativeValue = cdbext.createValue(value.address(), native_type)
|
||||
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)
|
||||
def handleItem(nativeFieldType, align):
|
||||
a = self.type_alignment(self.from_native_type(nativeFieldType))
|
||||
@@ -224,13 +224,13 @@ class Dumper(DumperBase):
|
||||
align = handleItem(f.type(), 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))
|
||||
if value is None:
|
||||
return ''
|
||||
return self.enumValue(value)
|
||||
|
||||
def enumExpression(self, enumType, enumValue):
|
||||
def enumExpression(self, enumType: str, enumValue: str) -> str:
|
||||
ns = self.qtNamespace()
|
||||
return ns + "Qt::" + enumType + "(" \
|
||||
+ ns + "Qt::" + enumType + "::" + enumValue + ")"
|
||||
@@ -238,25 +238,25 @@ class Dumper(DumperBase):
|
||||
def pokeValue(self, typeName, *args):
|
||||
return None
|
||||
|
||||
def parseAndEvaluate(self, exp):
|
||||
def parseAndEvaluate(self, exp: str) -> DumperBase.Value:
|
||||
return self.fromNativeValue(self.nativeParseAndEvaluate(exp))
|
||||
|
||||
def nativeParseAndEvaluate(self, exp):
|
||||
def nativeParseAndEvaluate(self, exp: str) -> cdbext.Value:
|
||||
return cdbext.parseAndEvaluate(exp)
|
||||
|
||||
def isWindowsTarget(self):
|
||||
def isWindowsTarget(self) -> bool:
|
||||
return True
|
||||
|
||||
def isQnxTarget(self):
|
||||
def isQnxTarget(self) -> bool:
|
||||
return False
|
||||
|
||||
def isArmArchitecture(self):
|
||||
def isArmArchitecture(self) -> bool:
|
||||
return False
|
||||
|
||||
def isMsvcTarget(self):
|
||||
def isMsvcTarget(self) -> bool:
|
||||
return True
|
||||
|
||||
def qtCoreModuleName(self):
|
||||
def qtCoreModuleName(self) -> str:
|
||||
modules = cdbext.listOfModules()
|
||||
# first check for an exact module name match
|
||||
for coreName in ['Qt6Core', 'Qt6Cored', 'Qt5Cored', 'Qt5Core', 'QtCored4', 'QtCore4']:
|
||||
@@ -272,7 +272,7 @@ class Dumper(DumperBase):
|
||||
return coreName
|
||||
return None
|
||||
|
||||
def qtDeclarativeModuleName(self):
|
||||
def qtDeclarativeModuleName(self) -> str:
|
||||
modules = cdbext.listOfModules()
|
||||
for declarativeModuleName in ['Qt6Qmld', 'Qt6Qml', 'Qt5Qmld', 'Qt5Qml']:
|
||||
if declarativeModuleName in modules:
|
||||
@@ -285,7 +285,7 @@ class Dumper(DumperBase):
|
||||
return declarativeModuleName
|
||||
return None
|
||||
|
||||
def qtHookDataSymbolName(self):
|
||||
def qtHookDataSymbolName(self) -> str:
|
||||
hookSymbolName = 'qtHookData'
|
||||
coreModuleName = self.qtCoreModuleName()
|
||||
if coreModuleName is not None:
|
||||
@@ -299,7 +299,7 @@ class Dumper(DumperBase):
|
||||
self.qtHookDataSymbolName = lambda: hookSymbolName
|
||||
return hookSymbolName
|
||||
|
||||
def qtDeclarativeHookDataSymbolName(self):
|
||||
def qtDeclarativeHookDataSymbolName(self) -> str:
|
||||
hookSymbolName = 'qtDeclarativeHookData'
|
||||
declarativeModuleName = self.qtDeclarativeModuleName()
|
||||
if declarativeModuleName is not None:
|
||||
@@ -314,7 +314,7 @@ class Dumper(DumperBase):
|
||||
self.qtDeclarativeHookDataSymbolName = lambda: hookSymbolName
|
||||
return hookSymbolName
|
||||
|
||||
def extractQtVersion(self):
|
||||
def extractQtVersion(self) -> int:
|
||||
try:
|
||||
qtVersion = self.parseAndEvaluate(
|
||||
'((void**)&%s)[2]' % self.qtHookDataSymbolName()).integer()
|
||||
@@ -329,7 +329,7 @@ class Dumper(DumperBase):
|
||||
return None
|
||||
return qtVersion
|
||||
|
||||
def putVtableItem(self, address):
|
||||
def putVtableItem(self, address: int):
|
||||
funcName = cdbext.getNameByAddress(address)
|
||||
if funcName is None:
|
||||
self.putItem(self.createPointerValue(address, 'void'))
|
||||
@@ -338,7 +338,7 @@ class Dumper(DumperBase):
|
||||
self.putType('void*')
|
||||
self.putAddress(address)
|
||||
|
||||
def putVTableChildren(self, item, itemCount):
|
||||
def putVTableChildren(self, item: DumperBase.Value, itemCount: int) -> int:
|
||||
p = item.address()
|
||||
for i in range(itemCount):
|
||||
deref = self.extractPointer(p)
|
||||
@@ -350,12 +350,12 @@ class Dumper(DumperBase):
|
||||
p += self.ptrSize()
|
||||
return itemCount
|
||||
|
||||
def ptrSize(self):
|
||||
def ptrSize(self) -> int:
|
||||
size = cdbext.pointerSize()
|
||||
self.ptrSize = lambda: size
|
||||
return size
|
||||
|
||||
def stripQintTypedefs(self, typeName):
|
||||
def stripQintTypedefs(self, typeName: str) -> str:
|
||||
if typeName.startswith('qint'):
|
||||
prefix = ''
|
||||
size = typeName[4:]
|
||||
@@ -375,7 +375,7 @@ class Dumper(DumperBase):
|
||||
else:
|
||||
return typeName
|
||||
|
||||
def lookupNativeType(self, name, module=0):
|
||||
def lookupNativeType(self, name: str, module=0) -> cdbext.Type:
|
||||
if name.startswith('void'):
|
||||
return FakeVoidType(name, self)
|
||||
return cdbext.lookupType(name, module)
|
||||
@@ -383,13 +383,13 @@ class Dumper(DumperBase):
|
||||
def reportResult(self, result, args):
|
||||
cdbext.reportResult('result={%s}' % result)
|
||||
|
||||
def readRawMemory(self, address, size):
|
||||
def readRawMemory(self, address: int, size: int) -> int:
|
||||
mem = cdbext.readRawMemory(address, size)
|
||||
if len(mem) != size:
|
||||
raise Exception("Invalid memory request: %d bytes from 0x%x" % (size, address))
|
||||
return mem
|
||||
|
||||
def findStaticMetaObject(self, type):
|
||||
def findStaticMetaObject(self, type: DumperBase.Type) -> int:
|
||||
ptr = 0
|
||||
if type.moduleName is not None:
|
||||
# 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):
|
||||
sys.stdout.write(stuff + "\n")
|
||||
|
||||
def findValueByExpression(self, exp):
|
||||
return cdbext.parseAndEvaluate(exp)
|
||||
|
||||
def nativeValueDereferenceReference(self, value):
|
||||
def nativeValueDereferenceReference(self, value: DumperBase.Value) -> DumperBase.Value:
|
||||
return self.nativeValueDereferencePointer(value)
|
||||
|
||||
def nativeValueDereferencePointer(self, value):
|
||||
def nativeValueDereferencePointer(self, value: DumperBase.Value) -> DumperBase.Value:
|
||||
def nativeVtCastValue(nativeValue):
|
||||
# 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
|
||||
@@ -490,7 +487,7 @@ class Dumper(DumperBase):
|
||||
def callHelper(self, rettype, value, function, args):
|
||||
raise Exception("cdb does not support calling functions")
|
||||
|
||||
def nameForCoreId(self, id):
|
||||
def nameForCoreId(self, id: int) -> DumperBase.Value:
|
||||
for dll in ['Utilsd', 'Utils']:
|
||||
idName = cdbext.call('%s!Utils::nameForId(%d)' % (dll, id))
|
||||
if idName is not None:
|
||||
@@ -500,7 +497,7 @@ class Dumper(DumperBase):
|
||||
def putCallItem(self, name, rettype, value, func, *args):
|
||||
return
|
||||
|
||||
def symbolAddress(self, symbolName):
|
||||
def symbolAddress(self, symbolName: str) -> int:
|
||||
res = self.nativeParseAndEvaluate(symbolName)
|
||||
return None if res is None else res.address()
|
||||
|
||||
@@ -726,7 +723,7 @@ class Dumper(DumperBase):
|
||||
self.putItem(value.dereference())
|
||||
|
||||
|
||||
def putCStyleArray(self, value):
|
||||
def putCStyleArray(self, value: DumperBase.Value):
|
||||
arrayType = value.type
|
||||
innerType = arrayType.target()
|
||||
address = value.address()
|
||||
@@ -886,26 +883,6 @@ class Dumper(DumperBase):
|
||||
self.putItem(derefValue)
|
||||
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):
|
||||
coreModuleName = self.qtCoreModuleName()
|
||||
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'):
|
||||
d.putItem(d.createValue(privAddress + absoluteDirEntryOffset, '@QString'))
|
||||
with SubItem(d, 'entryInfoList'):
|
||||
qdumpHelper_QList(d, privAddress + fileInfosOffset, '@QFileInfo')
|
||||
qdumpHelper_QList(d, d.createValue(privAddress + fileInfosOffset, '@QList<@QFileInfo>'), '@QFileInfo')
|
||||
with SubItem(d, 'entryList'):
|
||||
d.putItem(d.createValue(privAddress + filesOffset, '@QStringList'))
|
||||
d.putFields(value)
|
||||
@@ -1256,7 +1256,7 @@ def qdump__QLocale(d, value):
|
||||
|
||||
prefix = ns + 'QLocale::'
|
||||
try:
|
||||
if qtVersionAtLeast(0x060700):
|
||||
if d.qtVersionAtLeast(0x060700):
|
||||
res = d.call('const char *', value, 'name', prefix + 'TagSeparator::Underscore')
|
||||
else:
|
||||
res = d.call('const char *', value, 'name')
|
||||
|
@@ -21936,8 +21936,14 @@ Doppelklicken Sie einen Eintrag um ihn zu ändern.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Executable:</source>
|
||||
<comment>adjective</comment>
|
||||
<translation>Ausführbar:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Executable:</source>
|
||||
<comment>noun</comment>
|
||||
<translation>Ausführbare Datei:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Symbolic link:</source>
|
||||
<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>
|
||||
<source>Executable:</source>
|
||||
<comment>adjective</comment>
|
||||
<translation>Izvršavajuća:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Executable:</source>
|
||||
<comment>noun</comment>
|
||||
<translation>Izvršna datoteka:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Symbolic link:</source>
|
||||
<translation>Simbolička poveznica:</translation>
|
||||
|
@@ -18313,8 +18313,14 @@ will also disable the following plugins:
|
||||
</message>
|
||||
<message>
|
||||
<source>Executable:</source>
|
||||
<comment>adjective</comment>
|
||||
<translation>Можно запускать:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Executable:</source>
|
||||
<comment>noun</comment>
|
||||
<translation>Программа:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Symbolic link:</source>
|
||||
<translation>Символьная ссылка:</translation>
|
||||
|
@@ -17,6 +17,7 @@ Product {
|
||||
"designer/**/*",
|
||||
"glsl/**/*",
|
||||
"jsonschemas/**/*",
|
||||
"lua-plugins/**/*",
|
||||
"modeleditor/**/*",
|
||||
"qml/**/*",
|
||||
"qmldesigner/**/*",
|
||||
|
@@ -177,8 +177,11 @@ static inline int askMsgSendFailed()
|
||||
|
||||
static inline QStringList getPluginPaths()
|
||||
{
|
||||
QStringList rc(QDir::cleanPath(QApplication::applicationDirPath()
|
||||
+ '/' + RELATIVE_PLUGIN_PATH));
|
||||
QStringList rc;
|
||||
rc << (QDir::cleanPath(QApplication::applicationDirPath()
|
||||
+ '/' + RELATIVE_PLUGIN_PATH))
|
||||
<< (QDir::cleanPath(QApplication::applicationDirPath()
|
||||
+ '/' + RELATIVE_DATA_PATH + "/lua-plugins"));
|
||||
// Local plugin path: <localappdata>/plugins/<ideversion>
|
||||
// where <localappdata> is e.g.
|
||||
// "%LOCALAPPDATA%\QtProject\qtcreator" on Windows Vista and later
|
||||
|
@@ -17,9 +17,11 @@
|
||||
#endif
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QFileSystemWatcher>
|
||||
#include <QOperatingSystemVersion>
|
||||
#include <QRandomGenerator>
|
||||
#include <QRegularExpression>
|
||||
#include <QStandardPaths>
|
||||
#include <QStorageInfo>
|
||||
#include <QTemporaryFile>
|
||||
|
||||
@@ -33,7 +35,6 @@
|
||||
#include <qplatformdefs.h>
|
||||
#endif
|
||||
|
||||
#include <QStandardPaths>
|
||||
#include <algorithm>
|
||||
#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()));
|
||||
}
|
||||
|
||||
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() = default;
|
||||
@@ -767,6 +775,29 @@ expected_str<FilePath> DesktopDeviceFileAccess::createTempFile(const FilePath &f
|
||||
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
|
||||
{
|
||||
return QFileInfo(filePath.path()).lastModified();
|
||||
|
@@ -72,6 +72,8 @@ protected:
|
||||
const QByteArray &data) const;
|
||||
|
||||
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
|
||||
@@ -128,6 +130,7 @@ protected:
|
||||
|
||||
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
|
||||
|
@@ -313,6 +313,11 @@ bool FilePath::equalsCaseSensitive(const FilePath &other) const
|
||||
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.
|
||||
|
||||
|
@@ -55,6 +55,16 @@ public:
|
||||
|
||||
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
|
||||
{
|
||||
public:
|
||||
@@ -270,6 +280,8 @@ public:
|
||||
|
||||
bool equalsCaseSensitive(const FilePath &other) const;
|
||||
|
||||
Utils::expected_str<std::unique_ptr<FilePathWatcher>> watch() const;
|
||||
|
||||
private:
|
||||
// These are needed.
|
||||
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(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);
|
||||
timer->setSingleShot(true);
|
||||
timer->setInterval(1000);
|
||||
connect(m_editor, &QPlainTextEdit::textChanged, timer, qOverload<>(&QTimer::start));
|
||||
connect(timer, &QTimer::timeout, this, checkForItemChange);
|
||||
connect(m_editor, &Internal::TextEditHelper::lostFocus, this, [timer, checkForItemChange] {
|
||||
connect(timer, &QTimer::timeout, this, &NameValueItemsWidget::forceUpdateCheck);
|
||||
connect(m_editor, &Internal::TextEditHelper::lostFocus, this, [this, timer] {
|
||||
timer->stop();
|
||||
checkForItemChange();
|
||||
forceUpdateCheck();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -159,6 +152,15 @@ bool NameValueItemsWidget::editVariable(const QString &name, Selection selection
|
||||
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)
|
||||
: QDialog(parent)
|
||||
{
|
||||
|
@@ -29,6 +29,8 @@ public:
|
||||
enum class Selection { Name, Value };
|
||||
bool editVariable(const QString &name, Selection selection);
|
||||
|
||||
void forceUpdateCheck();
|
||||
|
||||
signals:
|
||||
void userChangedItems(const EnvironmentItems &items);
|
||||
|
||||
|
@@ -57,7 +57,7 @@ inline OsArch osArchFromString(const QString &architecture)
|
||||
return OsArchItanium;
|
||||
if (architecture == QLatin1String("arm"))
|
||||
return OsArchArm;
|
||||
if (architecture == QLatin1String("arm64"))
|
||||
if (architecture == QLatin1String("arm64") || architecture == QLatin1String("aarch64"))
|
||||
return OsArchArm64;
|
||||
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());
|
||||
}
|
||||
|
||||
FilePath PathChooser::filePath() const
|
||||
{
|
||||
return d->expandedPath(rawFilePath());
|
||||
return d->expandedPath(unexpandedFilePath());
|
||||
}
|
||||
|
||||
FilePath PathChooser::absoluteFilePath() const
|
||||
|
@@ -67,10 +67,10 @@ public:
|
||||
bool isValid() 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 rawFilePath() const; // The raw unexpanded input as FilePath.
|
||||
FilePath unexpandedFilePath() const; // The raw unexpanded input as FilePath.
|
||||
|
||||
FilePath baseDirectory() const;
|
||||
void setBaseDirectory(const FilePath &base);
|
||||
|
@@ -119,7 +119,3 @@ endif()
|
||||
add_subdirectory(qnx)
|
||||
add_subdirectory(mcusupport)
|
||||
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->setPromptDialogTitle(Tr::tr("Select Keystore File"));
|
||||
connect(keystoreLocationChooser, &PathChooser::textChanged, this, [this, keystoreLocationChooser] {
|
||||
const FilePath file = keystoreLocationChooser->rawFilePath();
|
||||
const FilePath file = keystoreLocationChooser->unexpandedFilePath();
|
||||
m_step->setKeystorePath(file);
|
||||
m_signPackageCheckBox->setChecked(!file.isEmpty());
|
||||
if (!file.isEmpty())
|
||||
|
@@ -151,7 +151,7 @@ ChooseDirectoryPage::ChooseDirectoryPage(CreateAndroidManifestWizard *wizard)
|
||||
m_layout->addRow(m_sourceDirectoryWarning);
|
||||
|
||||
connect(m_androidPackageSourceDir, &PathChooser::textChanged, m_wizard, [this] {
|
||||
m_wizard->setDirectory(m_androidPackageSourceDir->rawFilePath());
|
||||
m_wizard->setDirectory(m_androidPackageSourceDir->unexpandedFilePath());
|
||||
});
|
||||
|
||||
if (wizard->copyGradle()) {
|
||||
|
@@ -20,10 +20,13 @@ using namespace Utils;
|
||||
namespace ClangTools {
|
||||
namespace Internal {
|
||||
|
||||
static TextMarkCategory clangToolsCategory()
|
||||
{
|
||||
return {Tr::tr("Clang Tools"), Id(Constants::DIAGNOSTIC_MARK_ID)};
|
||||
}
|
||||
|
||||
DiagnosticMark::DiagnosticMark(const Diagnostic &diagnostic, TextDocument *document)
|
||||
: TextMark(document,
|
||||
diagnostic.location.line,
|
||||
{Tr::tr("Clang Tools"), Id(Constants::DIAGNOSTIC_MARK_ID)})
|
||||
: TextMark(document, diagnostic.location.line, clangToolsCategory())
|
||||
, m_diagnostic(diagnostic)
|
||||
{
|
||||
setSettingsPage(Constants::SETTINGS_PAGE_ID);
|
||||
@@ -60,7 +63,8 @@ DiagnosticMark::DiagnosticMark(const Diagnostic &diagnostic, TextDocument *docum
|
||||
}
|
||||
|
||||
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()
|
||||
|
@@ -99,12 +99,12 @@ SettingsWidget::~SettingsWidget()
|
||||
|
||||
FilePath SettingsWidget::clangTidyPath() const
|
||||
{
|
||||
return m_clangTidyPathChooser->rawFilePath();
|
||||
return m_clangTidyPathChooser->unexpandedFilePath();
|
||||
}
|
||||
|
||||
FilePath SettingsWidget::clazyStandalonePath() const
|
||||
{
|
||||
return m_clazyStandalonePathChooser->rawFilePath();
|
||||
return m_clazyStandalonePathChooser->unexpandedFilePath();
|
||||
}
|
||||
|
||||
// ClangToolsOptionsPage
|
||||
|
@@ -177,7 +177,7 @@ SettingsPageWidget::SettingsPageWidget()
|
||||
void SettingsPageWidget::apply()
|
||||
{
|
||||
ClearCaseSettings rc;
|
||||
rc.ccCommand = commandPathChooser->rawFilePath().toString();
|
||||
rc.ccCommand = commandPathChooser->unexpandedFilePath().toString();
|
||||
rc.ccBinaryPath = commandPathChooser->filePath();
|
||||
rc.timeOutS = timeOutSpinBox->value();
|
||||
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
|
||||
fileToRename = projectFileArgumentPosition(targetName, oldRelPathName);
|
||||
} while (fileToRename);
|
||||
} while (fileToRename && !fileToRename->fromGlobbing);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1977,6 +1977,9 @@ static FilePaths librarySearchPaths(const CMakeBuildSystem *bs, const QString &b
|
||||
|
||||
const QList<BuildTargetInfo> CMakeBuildSystem::appTargets() const
|
||||
{
|
||||
const CMakeConfig &cm = configurationFromCMake();
|
||||
QString emulator = cm.stringValueOf("CMAKE_CROSSCOMPILING_EMULATOR");
|
||||
|
||||
QList<BuildTargetInfo> appTargetList;
|
||||
const bool forAndroid = DeviceTypeKitAspect::deviceTypeId(kit())
|
||||
== Android::Constants::ANDROID_DEVICE_TYPE;
|
||||
@@ -1989,6 +1992,15 @@ const QList<BuildTargetInfo> CMakeBuildSystem::appTargets() const
|
||||
|
||||
BuildTargetInfo bti;
|
||||
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.projectFilePath = ct.sourceDirectory.cleanPath();
|
||||
bti.workingDirectory = ct.workingDirectory;
|
||||
|
@@ -7,6 +7,7 @@
|
||||
|
||||
#include <projectexplorer/projectmacro.h>
|
||||
#include <projectexplorer/projectnodes.h>
|
||||
#include <projectexplorer/runconfigurationaspects.h>
|
||||
|
||||
#include <utils/fileutils.h>
|
||||
|
||||
@@ -30,6 +31,7 @@ class CMAKE_EXPORT CMakeBuildTarget
|
||||
public:
|
||||
QString title;
|
||||
Utils::FilePath executable; // TODO: rename to output?
|
||||
QList<ProjectExplorer::Launcher> launchers;
|
||||
TargetType targetType = UtilityType;
|
||||
bool linksToQtGui = false;
|
||||
bool qtcRunnable = true;
|
||||
|
@@ -94,8 +94,8 @@ void ConfigModelItemDelegate::setModelData(QWidget *editor, QAbstractItemModel *
|
||||
ConfigModel::DataItem data = ConfigModel::dataItemFromIndex(index);
|
||||
if (data.type == ConfigModel::DataItem::FILE || data.type == ConfigModel::DataItem::DIRECTORY) {
|
||||
auto edit = static_cast<PathChooser *>(editor);
|
||||
if (edit->rawFilePath().toString() != data.value)
|
||||
model->setData(index, edit->rawFilePath().toString(), Qt::EditRole);
|
||||
if (edit->unexpandedFilePath().toString() != data.value)
|
||||
model->setData(index, edit->unexpandedFilePath().toString(), Qt::EditRole);
|
||||
return;
|
||||
} else if (!data.values.isEmpty()) {
|
||||
auto edit = static_cast<QComboBox *>(editor);
|
||||
|
@@ -342,6 +342,22 @@ static CMakeBuildTarget toBuildTarget(const TargetDetails &t,
|
||||
}
|
||||
ct.libraryDirectories = filteredUnique(librarySeachPaths);
|
||||
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;
|
||||
}
|
||||
|
@@ -11,6 +11,7 @@
|
||||
#include <projectexplorer/rawprojectpart.h>
|
||||
|
||||
#include <utils/algorithm.h>
|
||||
#include <utils/filepath.h>
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
@@ -197,6 +197,7 @@ public:
|
||||
QList<Utils::FilePath> artifacts;
|
||||
QString installPrefix;
|
||||
std::vector<InstallDestination> installDestination;
|
||||
QList<ProjectExplorer::LauncherInfo> launcherInfos;
|
||||
std::optional<LinkInfo> link;
|
||||
std::optional<ArchiveInfo> archive;
|
||||
std::vector<DependencyInfo> dependencies;
|
||||
|
@@ -563,7 +563,7 @@ ExternalToolConfig::ExternalToolConfig()
|
||||
|
||||
Form {
|
||||
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("Working directory:"), m_workingDirectory, br,
|
||||
outputLabel, m_outputBehavior, br,
|
||||
@@ -700,12 +700,12 @@ void ExternalToolConfig::updateItem(const QModelIndex &index)
|
||||
tool->setDescription(m_description->text());
|
||||
FilePaths executables = tool->executables();
|
||||
if (executables.size() > 0)
|
||||
executables[0] = m_executable->rawFilePath();
|
||||
executables[0] = m_executable->unexpandedFilePath();
|
||||
else
|
||||
executables << m_executable->rawFilePath();
|
||||
executables << m_executable->unexpandedFilePath();
|
||||
tool->setExecutables(executables);
|
||||
tool->setArguments(m_arguments->text());
|
||||
tool->setWorkingDirectory(m_workingDirectory->rawFilePath());
|
||||
tool->setWorkingDirectory(m_workingDirectory->unexpandedFilePath());
|
||||
tool->setBaseEnvironmentProviderId(Id::fromSetting(m_baseEnvironment->currentData()));
|
||||
tool->setEnvironmentUserChanges(m_environment);
|
||||
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("Readable:"), m_readable, 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
|
||||
},
|
||||
buttonBox
|
||||
|
@@ -220,7 +220,7 @@ bool SpotlightLocatorFilter::openConfigDialog(QWidget *parent, bool &needsRefres
|
||||
caseSensitiveArgumentsEdit->setText(m_caseSensitiveArguments);
|
||||
auto sortResults = new QCheckBox(Tr::tr("Sort results"));
|
||||
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("Case sensitive:"), caseSensitiveArgumentsEdit);
|
||||
layout->addRow({}, sortResults);
|
||||
@@ -231,7 +231,7 @@ bool SpotlightLocatorFilter::openConfigDialog(QWidget *parent, bool &needsRefres
|
||||
chooser->addSupportedWidget(caseSensitiveArgumentsEdit);
|
||||
const bool accepted = ILocatorFilter::openConfigDialog(parent, &configWidget);
|
||||
if (accepted) {
|
||||
m_command = commandEdit->rawFilePath().toString();
|
||||
m_command = commandEdit->unexpandedFilePath().toString();
|
||||
m_arguments = argumentsEdit->text();
|
||||
m_caseSensitiveArguments = caseSensitiveArgumentsEdit->text();
|
||||
m_sortResults = sortResults->isChecked();
|
||||
|
@@ -239,6 +239,8 @@ void DapClient::emitSignals(const QJsonDocument &doc)
|
||||
type = DapResponseType::SetFunctionBreakpoints;
|
||||
} else if (command == "attach") {
|
||||
type = DapResponseType::Attach;
|
||||
} else if (command == "launch") {
|
||||
type = DapResponseType::Launch;
|
||||
}
|
||||
emit responseReady(type, ob);
|
||||
return;
|
||||
|
@@ -55,6 +55,7 @@ enum class DapResponseType
|
||||
SetBreakpoints,
|
||||
SetFunctionBreakpoints,
|
||||
Attach,
|
||||
Launch,
|
||||
Unknown
|
||||
};
|
||||
|
||||
|
@@ -645,6 +645,7 @@ void DapEngine::readDapStandardError()
|
||||
void DapEngine::handleResponse(DapResponseType type, const QJsonObject &response)
|
||||
{
|
||||
const QString command = response.value("command").toString();
|
||||
const bool success = response.value("success").toBool();
|
||||
|
||||
switch (type) {
|
||||
case DapResponseType::Initialize:
|
||||
@@ -675,7 +676,7 @@ void DapEngine::handleResponse(DapResponseType type, const QJsonObject &response
|
||||
case DapResponseType::StepIn:
|
||||
case DapResponseType::StepOut:
|
||||
case DapResponseType::StepOver:
|
||||
if (response.value("success").toBool()) {
|
||||
if (success) {
|
||||
showMessage(command, LogDebug);
|
||||
notifyInferiorRunOk();
|
||||
} else {
|
||||
@@ -692,11 +693,21 @@ void DapEngine::handleResponse(DapResponseType type, const QJsonObject &response
|
||||
case DapResponseType::SetBreakpoints:
|
||||
handleBreakpointResponse(response);
|
||||
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:
|
||||
showMessage("UNKNOWN RESPONSE:" + command);
|
||||
};
|
||||
|
||||
if (response.contains("success") && !response.value("success").toBool()) {
|
||||
if (!success) {
|
||||
showMessage(QString("DAP COMMAND FAILED: %1").arg(command));
|
||||
qCDebug(logCategory()) << "DAP COMMAND FAILED:" << command;
|
||||
return;
|
||||
|
@@ -115,6 +115,14 @@ LldbDapEngine::LldbDapEngine()
|
||||
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 sourcePathMapping;
|
||||
@@ -148,19 +156,25 @@ void LldbDapEngine::handleDapInitialize()
|
||||
// * https://github.com/llvm/llvm-project/blob/main/lldb/tools/lldb-dap/package.json
|
||||
|
||||
const DebuggerRunParameters &rp = runParameters();
|
||||
const QJsonArray map = sourceMap();
|
||||
const QJsonArray commands = preRunCommands();
|
||||
|
||||
if (!isLocalAttachEngine()) {
|
||||
m_dapClient->postRequest(
|
||||
"launch",
|
||||
QJsonObject{
|
||||
const QJsonArray env = environment();
|
||||
QJsonObject launchJson{
|
||||
{"noDebug", false},
|
||||
{"program", rp.inferior.command.executable().path()},
|
||||
{"args", rp.inferior.command.arguments()},
|
||||
{"cwd", rp.inferior.workingDirectory.path()},
|
||||
{"sourceMap", sourceMap()},
|
||||
{"preRunCommands", preRunCommands()},
|
||||
{"env", env},
|
||||
{"__restart", ""},
|
||||
});
|
||||
};
|
||||
if (!map.isEmpty())
|
||||
launchJson.insert("sourceMap", map);
|
||||
if (!commands.isEmpty())
|
||||
launchJson.insert("preRunCommands", commands);
|
||||
|
||||
m_dapClient->postRequest("launch", launchJson);
|
||||
|
||||
qCDebug(logCategory()) << "handleDapLaunch";
|
||||
return;
|
||||
@@ -168,15 +182,17 @@ void LldbDapEngine::handleDapInitialize()
|
||||
|
||||
QTC_ASSERT(state() == EngineRunRequested, qCDebug(logCategory()) << state());
|
||||
|
||||
m_dapClient->postRequest(
|
||||
"attach",
|
||||
QJsonObject{
|
||||
QJsonObject attachJson{
|
||||
{"program", rp.inferior.command.executable().path()},
|
||||
{"pid", QString::number(rp.attachPID.pid())},
|
||||
{"sourceMap", sourceMap()},
|
||||
{"preRunCommands", preRunCommands()},
|
||||
{"__restart", ""},
|
||||
});
|
||||
};
|
||||
if (!map.isEmpty())
|
||||
attachJson.insert("sourceMap", map);
|
||||
if (!commands.isEmpty())
|
||||
attachJson.insert("preRunCommands", commands);
|
||||
|
||||
m_dapClient->postRequest("attach", attachJson);
|
||||
|
||||
qCDebug(logCategory()) << "handleDapAttach";
|
||||
}
|
||||
|
@@ -22,6 +22,7 @@ private:
|
||||
bool acceptsBreakpoint(const BreakpointParameters &bp) const override;
|
||||
const QLoggingCategory &logCategory() override;
|
||||
|
||||
QJsonArray environment() const;
|
||||
QJsonArray sourceMap() const;
|
||||
QJsonArray preRunCommands() const;
|
||||
};
|
||||
|
@@ -309,7 +309,7 @@ QString DebuggerSourcePathMappingWidget::editSourceField() const
|
||||
|
||||
QString DebuggerSourcePathMappingWidget::editTargetField() const
|
||||
{
|
||||
return m_targetChooser->rawFilePath().toString();
|
||||
return m_targetChooser->unexpandedFilePath().toString();
|
||||
}
|
||||
|
||||
void DebuggerSourcePathMappingWidget::setEditFieldMapping(const Mapping &m)
|
||||
|
@@ -163,10 +163,10 @@ int AttachCoreDialog::exec()
|
||||
{
|
||||
connect(d->symbolFileName, &PathChooser::validChanged, this, &AttachCoreDialog::changed);
|
||||
connect(d->coreFileName, &PathChooser::validChanged, this, [this] {
|
||||
coreFileChanged(d->coreFileName->rawFilePath());
|
||||
coreFileChanged(d->coreFileName->unexpandedFilePath());
|
||||
});
|
||||
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->buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
||||
|
@@ -54,6 +54,26 @@ bool DockerApi::canConnect()
|
||||
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)
|
||||
{
|
||||
if (async) {
|
||||
|
@@ -44,6 +44,8 @@ public:
|
||||
static void recheckDockerDaemon();
|
||||
QFuture<Utils::expected_str<QList<Network>>> networks();
|
||||
|
||||
bool isContainerRunning(const QString &containerId);
|
||||
|
||||
signals:
|
||||
void dockerDaemonAvailableChanged();
|
||||
|
||||
|
@@ -90,7 +90,7 @@ public:
|
||||
&Utils::PathChooser::textChanged,
|
||||
bc,
|
||||
[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->setHistoryCompleter("IncrediBuild.BuildConsole.MakeCommand.History");
|
||||
connect(d->makePathChooser, &PathChooser::rawPathChanged, this, [this] {
|
||||
d->m_activeCommandBuilder->setCommand(d->makePathChooser->rawFilePath());
|
||||
d->m_activeCommandBuilder->setCommand(d->makePathChooser->unexpandedFilePath());
|
||||
updateGui();
|
||||
});
|
||||
}
|
||||
|
@@ -82,6 +82,13 @@ QtcPlugin {
|
||||
]
|
||||
}
|
||||
|
||||
Group {
|
||||
name: "Lua images rcc"
|
||||
Qt.core.resourcePrefix: "lua/images/"
|
||||
fileTags: "qt.core.resource_data"
|
||||
files: "images/**"
|
||||
}
|
||||
|
||||
Export {
|
||||
Depends { name: "sol2" }
|
||||
Depends { name: "lua546" }
|
||||
|
@@ -373,11 +373,9 @@ QJsonValue LuaEngine::toJson(const sol::table &table)
|
||||
QStringList LuaEngine::variadicToStringList(const sol::variadic_args &vargs)
|
||||
{
|
||||
QStringList strings;
|
||||
int n = vargs.size();
|
||||
int i;
|
||||
for (i = 1; i <= n; i++) {
|
||||
for (size_t i = 1, n = vargs.size(); i <= n; i++) {
|
||||
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)
|
||||
strings.append(QString::fromUtf8(s, l));
|
||||
}
|
||||
|
@@ -51,7 +51,7 @@ protected:
|
||||
public:
|
||||
using PackageProvider = std::function<sol::object(sol::state_view)>;
|
||||
|
||||
~LuaEngine();
|
||||
~LuaEngine() override;
|
||||
static LuaEngine &instance();
|
||||
|
||||
Utils::expected_str<LuaPluginSpec *> loadPlugin(const Utils::FilePath &path);
|
||||
|
@@ -144,14 +144,11 @@ bool LuaPluginSpec::delayedInitialize()
|
||||
}
|
||||
ExtensionSystem::IPlugin::ShutdownFlag LuaPluginSpec::stop()
|
||||
{
|
||||
d->activeLuaState.reset();
|
||||
d->activeLuaState->stack_clear();
|
||||
return ExtensionSystem::IPlugin::ShutdownFlag::SynchronousShutdown;
|
||||
}
|
||||
|
||||
void LuaPluginSpec::kill()
|
||||
{
|
||||
d->activeLuaState.reset();
|
||||
}
|
||||
void LuaPluginSpec::kill() {}
|
||||
|
||||
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.",
|
||||
"trDisplayName": "Qt Creator Lua Plugin",
|
||||
"trDisplayCategory": "Library",
|
||||
"iconText": "LuaP",
|
||||
"icon": "icon.png",
|
||||
"iconKind": "Themed",
|
||||
"featuresRequired": [],
|
||||
"options": [
|
||||
{
|
||||
|
@@ -7,5 +7,7 @@
|
||||
<file>plugin/project.json</file>
|
||||
<file>plugin/wizard.json</file>
|
||||
<file>plugin/.luarc.json</file>
|
||||
<file>plugin/icon.png</file>
|
||||
<file>plugin/icon@2x.png</file>
|
||||
</qresource>
|
||||
</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(m_fileChooser, &PathChooser::textChanged, this, [this] {
|
||||
setPath(m_fileChooser->rawFilePath());
|
||||
setPath(m_fileChooser->unexpandedFilePath());
|
||||
});
|
||||
|
||||
connect(this, &McuPackage::changed, m_fileChooser, [this] {
|
||||
|
@@ -141,7 +141,7 @@ public:
|
||||
|
||||
// Connect
|
||||
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());
|
||||
QTC_ASSERT(tc, return);
|
||||
tc->setCompilerCommand(path);
|
||||
|
@@ -55,8 +55,6 @@ Project {
|
||||
"languageclient/languageclient.qbs",
|
||||
"languageclient/lualanguageclient/lualanguageclient.qbs",
|
||||
"lua/lua.qbs",
|
||||
"luals/luals.qbs",
|
||||
"luatests/luatests.qbs",
|
||||
"macros/macros.qbs",
|
||||
"marketplace/marketplace.qbs",
|
||||
"mcusupport/mcusupport.qbs",
|
||||
@@ -81,7 +79,6 @@ Project {
|
||||
"qtsupport/qtsupport.qbs",
|
||||
"remotelinux/remotelinux.qbs",
|
||||
"resourceeditor/resourceeditor.qbs",
|
||||
"rustls/rustls.qbs",
|
||||
"saferenderer/saferenderer.qbs",
|
||||
"screenrecorder/screenrecorder.qbs",
|
||||
"scxmleditor/scxmleditor.qbs",
|
||||
@@ -90,7 +87,6 @@ Project {
|
||||
"squish/squish.qbs",
|
||||
"studiowelcome/studiowelcome.qbs",
|
||||
"subversion/subversion.qbs",
|
||||
"tellajoke/tellajoke.qbs",
|
||||
"terminal/terminal.qbs",
|
||||
"texteditor/texteditor.qbs",
|
||||
"todo/todo.qbs",
|
||||
|
@@ -5,12 +5,15 @@
|
||||
|
||||
#include "projectexplorer_export.h"
|
||||
|
||||
#include "runconfiguration.h"
|
||||
|
||||
#include <utils/environment.h>
|
||||
#include <utils/filepath.h>
|
||||
|
||||
#include <QList>
|
||||
|
||||
namespace ProjectExplorer {
|
||||
class Launcher;
|
||||
|
||||
class PROJECTEXPLORER_EXPORT BuildTargetInfo
|
||||
{
|
||||
@@ -19,6 +22,7 @@ public:
|
||||
QString displayName;
|
||||
QString displayNameUniquifier;
|
||||
|
||||
QList<Launcher> launchers;
|
||||
Utils::FilePath targetFilePath;
|
||||
Utils::FilePath projectFilePath;
|
||||
Utils::FilePath workingDirectory;
|
||||
|
@@ -70,6 +70,7 @@ private:
|
||||
FilePath executableToRun(const BuildTargetInfo &targetInfo) const;
|
||||
|
||||
const Kind m_kind;
|
||||
LauncherAspect launcher{this};
|
||||
EnvironmentAspect environment{this};
|
||||
ExecutableAspect executable{this};
|
||||
ArgumentsAspect arguments{this};
|
||||
@@ -90,6 +91,8 @@ void DesktopRunConfiguration::updateTargetInformation()
|
||||
auto terminalAspect = aspect<TerminalAspect>();
|
||||
terminalAspect->setUseTerminalHint(bti.targetFilePath.needsDevice() ? false : bti.usesTerminal);
|
||||
terminalAspect->setEnabled(!bti.targetFilePath.needsDevice());
|
||||
auto launcherAspect = aspect<LauncherAspect>();
|
||||
launcherAspect->setVisible(false);
|
||||
|
||||
if (m_kind == Qmake) {
|
||||
|
||||
@@ -121,6 +124,12 @@ void DesktopRunConfiguration::updateTargetInformation()
|
||||
|
||||
} 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<WorkingDirectoryAspect>()->setDefaultWorkingDirectory(bti.workingDirectory);
|
||||
emit aspect<EnvironmentAspect>()->environmentChanged();
|
||||
|
@@ -139,6 +139,7 @@ public:
|
||||
IDevice::MachineType machineType = IDevice::Hardware;
|
||||
OsType osType = OsTypeOther;
|
||||
DeviceFileAccess *fileAccess = nullptr;
|
||||
std::function<DeviceFileAccess *()> fileAccessFactory;
|
||||
int version = 0; // This is used by devices that have been added by the SDK.
|
||||
|
||||
Utils::SynchronizedValue<SshParameters> sshParameters;
|
||||
@@ -251,6 +252,9 @@ bool IDevice::isAnyUnixDevice() const
|
||||
|
||||
DeviceFileAccess *IDevice::fileAccess() const
|
||||
{
|
||||
if (d->fileAccessFactory)
|
||||
return d->fileAccessFactory();
|
||||
|
||||
return d->fileAccess;
|
||||
}
|
||||
|
||||
@@ -341,6 +345,11 @@ void IDevice::setFileAccess(DeviceFileAccess *fileAccess)
|
||||
d->fileAccess = fileAccess;
|
||||
}
|
||||
|
||||
void IDevice::setFileAccess(std::function<Utils::DeviceFileAccess *()> fileAccessFactory)
|
||||
{
|
||||
d->fileAccessFactory = fileAccessFactory;
|
||||
}
|
||||
|
||||
IDevice::DeviceInfo IDevice::deviceInformation() const
|
||||
{
|
||||
const QString key = Tr::tr("Device");
|
||||
|
@@ -241,6 +241,7 @@ protected:
|
||||
void setDisplayType(const QString &type);
|
||||
void setOsType(Utils::OsType osType);
|
||||
void setFileAccess(Utils::DeviceFileAccess *fileAccess);
|
||||
void setFileAccess(std::function<Utils::DeviceFileAccess *()> fileAccessFactory);
|
||||
|
||||
private:
|
||||
IDevice(const IDevice &) = delete;
|
||||
|
@@ -69,7 +69,7 @@ void EnvironmentAspect::setUserEnvironmentChanges(const Utils::EnvironmentItems
|
||||
Utils::Environment EnvironmentAspect::environment() const
|
||||
{
|
||||
Environment env = modifiedBaseEnvironment();
|
||||
env.modify(m_userChanges);
|
||||
env.modify(userEnvironmentChanges());
|
||||
return env;
|
||||
}
|
||||
|
||||
@@ -165,4 +165,9 @@ Environment EnvironmentAspect::BaseEnvironment::unmodifiedBaseEnvironment() cons
|
||||
return getter ? getter() : Environment();
|
||||
}
|
||||
|
||||
Utils::EnvironmentItems EnvironmentAspect::userEnvironmentChanges() const
|
||||
{
|
||||
emit userChangesUpdateRequested();
|
||||
return m_userChanges;
|
||||
}
|
||||
} // namespace ProjectExplorer
|
||||
|
@@ -32,7 +32,7 @@ public:
|
||||
int baseEnvironmentBase() const;
|
||||
void setBaseEnvironmentBase(int base);
|
||||
|
||||
Utils::EnvironmentItems userEnvironmentChanges() const { return m_userChanges; }
|
||||
Utils::EnvironmentItems userEnvironmentChanges() const;
|
||||
void setUserEnvironmentChanges(const Utils::EnvironmentItems &diff);
|
||||
|
||||
int addSupportedBaseEnvironment(const QString &displayName,
|
||||
@@ -68,6 +68,7 @@ signals:
|
||||
void baseEnvironmentChanged();
|
||||
void userEnvironmentChangesChanged(const Utils::EnvironmentItems &diff);
|
||||
void environmentChanged();
|
||||
void userChangesUpdateRequested() const;
|
||||
|
||||
protected:
|
||||
void fromMap(const Utils::Store &map) override;
|
||||
|
@@ -26,6 +26,10 @@ EnvironmentAspectWidget::EnvironmentAspectWidget(EnvironmentAspect *aspect)
|
||||
{
|
||||
QTC_CHECK(m_aspect);
|
||||
|
||||
connect(m_aspect, &EnvironmentAspect::userChangesUpdateRequested, this, [this] {
|
||||
m_environmentWidget->forceUpdateCheck();
|
||||
});
|
||||
|
||||
setContentsMargins(0, 0, 0, 0);
|
||||
auto topLayout = new QVBoxLayout(this);
|
||||
topLayout->setContentsMargins(0, 0, 0, 25);
|
||||
|
@@ -332,6 +332,7 @@ void EnvironmentWidget::setBaseEnvironmentText(const QString &text)
|
||||
|
||||
Utils::EnvironmentItems EnvironmentWidget::userChanges() const
|
||||
{
|
||||
forceUpdateCheck();
|
||||
return d->m_model->userChanges();
|
||||
}
|
||||
|
||||
@@ -352,6 +353,11 @@ void EnvironmentWidget::expand()
|
||||
d->m_detailsContainer->setState(Utils::DetailsWidget::Expanded);
|
||||
}
|
||||
|
||||
void EnvironmentWidget::forceUpdateCheck() const
|
||||
{
|
||||
d->m_editor.forceUpdateCheck();
|
||||
}
|
||||
|
||||
void EnvironmentWidget::updateSummaryText()
|
||||
{
|
||||
// The summary is redundant with the text edit, so we hide it on expansion.
|
||||
|
@@ -38,6 +38,8 @@ public:
|
||||
|
||||
void expand();
|
||||
|
||||
void forceUpdateCheck() const;
|
||||
|
||||
signals:
|
||||
void userChangesChanged();
|
||||
void detailsVisibleChanged(bool visible);
|
||||
|