Merge remote-tracking branch 'origin/14.0'

Conflicts:
	src/plugins/qmljseditor/qmljseditingsettingspage.cpp
	src/plugins/qmljseditor/qmllssettings.h

Change-Id: I49b97101467a6e80653c0f5f3e3fe5801dca5274
This commit is contained in:
Eike Ziller
2024-06-21 13:54:42 +02:00
123 changed files with 1005 additions and 308 deletions

View File

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

View File

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.4 KiB

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View File

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

View File

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

View 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}
*/

View File

@@ -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}
*/ */

View File

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

View File

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

View File

@@ -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}
*/ */

View File

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

View File

@@ -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"
} }
] ]

View File

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

View File

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

View 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 : ...

View File

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

View File

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

View File

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

View File

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

View File

@@ -17,6 +17,7 @@ Product {
"designer/**/*", "designer/**/*",
"glsl/**/*", "glsl/**/*",
"jsonschemas/**/*", "jsonschemas/**/*",
"lua-plugins/**/*",
"modeleditor/**/*", "modeleditor/**/*",
"qml/**/*", "qml/**/*",
"qmldesigner/**/*", "qmldesigner/**/*",

View File

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

View File

@@ -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();

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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()) {

View File

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

View File

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

View File

@@ -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();

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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()));

View File

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

View File

@@ -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();

View File

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

View File

@@ -55,6 +55,7 @@ enum class DapResponseType
SetBreakpoints, SetBreakpoints,
SetFunctionBreakpoints, SetFunctionBreakpoints,
Attach, Attach,
Launch,
Unknown Unknown
}; };

View File

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

View File

@@ -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";
} }

View File

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

View File

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

View File

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

View File

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

View File

@@ -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();

View File

@@ -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());
}); });
} }
}; };

View File

@@ -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();
}); });
} }

View File

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

View File

@@ -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));
} }

View File

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

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 887 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@@ -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": [
{ {

View File

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

View File

@@ -1,4 +0,0 @@
add_qtc_lua_plugin(luals
SOURCES luals/luals.lua
luals/init.lua
)

View File

@@ -1,8 +0,0 @@
QtcLuaPlugin {
name: "luals"
luafiles: [
"init.lua",
"luals.lua",
]
}

View File

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

View File

@@ -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",
]
}

View File

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

View File

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

View File

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

View File

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

View File

@@ -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();

View File

@@ -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");

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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