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

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

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

View File

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

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

View File

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

View File

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

View File

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

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

View File

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

View File

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

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

View File

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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());
}
FilePath PathChooser::filePath() const
{
return d->expandedPath(rawFilePath());
return d->expandedPath(unexpandedFilePath());
}
FilePath PathChooser::absoluteFilePath() const

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -44,6 +44,8 @@ public:
static void recheckDockerDaemon();
QFuture<Utils::expected_str<QList<Network>>> networks();
bool isContainerRunning(const QString &containerId);
signals:
void dockerDaemonAvailableChanged();

View File

@@ -90,7 +90,7 @@ public:
&Utils::PathChooser::textChanged,
bc,
[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->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();
});
}

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 {
Depends { name: "sol2" }
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 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));
}

View File

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

View File

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

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.",
"trDisplayName": "Qt Creator Lua Plugin",
"trDisplayCategory": "Library",
"iconText": "LuaP",
"icon": "icon.png",
"iconKind": "Themed",
"featuresRequired": [],
"options": [
{

View File

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

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(m_fileChooser, &PathChooser::textChanged, this, [this] {
setPath(m_fileChooser->rawFilePath());
setPath(m_fileChooser->unexpandedFilePath());
});
connect(this, &McuPackage::changed, m_fileChooser, [this] {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -38,6 +38,8 @@ public:
void expand();
void forceUpdateCheck() const;
signals:
void userChangesChanged();
void detailsVisibleChanged(bool visible);

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