diff --git a/cmake/QtCreatorAPI.cmake b/cmake/QtCreatorAPI.cmake index c0f61301111..c53b479982d 100644 --- a/cmake/QtCreatorAPI.cmake +++ b/cmake/QtCreatorAPI.cmake @@ -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() diff --git a/dist/changelog/changes-14.0.0.md b/dist/changelog/changes-14.0.0.md index 31a3e5daa04..7d14123acae 100644 --- a/dist/changelog/changes-14.0.0.md +++ b/dist/changelog/changes-14.0.0.md @@ -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 diff --git a/doc/qtcreator/images/qtcreator-build-environment.webp b/doc/qtcreator/images/qtcreator-build-environment.webp index 48bf4753d24..9cc53e85148 100644 Binary files a/doc/qtcreator/images/qtcreator-build-environment.webp and b/doc/qtcreator/images/qtcreator-build-environment.webp differ diff --git a/doc/qtcreator/images/qtcreator-edit-environment.webp b/doc/qtcreator/images/qtcreator-edit-environment.webp index f68eb52540e..55e04cc70c1 100644 Binary files a/doc/qtcreator/images/qtcreator-edit-environment.webp and b/doc/qtcreator/images/qtcreator-edit-environment.webp differ diff --git a/doc/qtcreator/images/qtcreator-preferences-build-run-general.webp b/doc/qtcreator/images/qtcreator-preferences-build-run-general.webp index 4826e22fc62..6a0bf6f4811 100644 Binary files a/doc/qtcreator/images/qtcreator-preferences-build-run-general.webp and b/doc/qtcreator/images/qtcreator-preferences-build-run-general.webp differ diff --git a/doc/qtcreator/images/qtcreator-project-settings-cmake.webp b/doc/qtcreator/images/qtcreator-project-settings-cmake.webp new file mode 100644 index 00000000000..f37c521a866 Binary files /dev/null and b/doc/qtcreator/images/qtcreator-project-settings-cmake.webp differ diff --git a/doc/qtcreator/images/qtcreator-projects-environment.webp b/doc/qtcreator/images/qtcreator-projects-environment.webp index eeaed5eaa00..6b33d698522 100644 Binary files a/doc/qtcreator/images/qtcreator-projects-environment.webp and b/doc/qtcreator/images/qtcreator-projects-environment.webp differ diff --git a/doc/qtcreator/images/qtcreator-projects-kits.webp b/doc/qtcreator/images/qtcreator-projects-kits.webp index 827037b0223..38c542c9d14 100644 Binary files a/doc/qtcreator/images/qtcreator-projects-kits.webp and b/doc/qtcreator/images/qtcreator-projects-kits.webp differ diff --git a/doc/qtcreator/images/qtcreator-run-environment.webp b/doc/qtcreator/images/qtcreator-run-environment.webp index 3a0313f994d..7bdd69ebab8 100644 Binary files a/doc/qtcreator/images/qtcreator-run-environment.webp and b/doc/qtcreator/images/qtcreator-run-environment.webp differ diff --git a/doc/qtcreator/src/cmake/creator-projects-cmake-presets.qdoc b/doc/qtcreator/src/cmake/creator-projects-cmake-presets.qdoc index 050b0b1f8c7..41937eb6b92 100644 --- a/doc/qtcreator/src/cmake/creator-projects-cmake-presets.qdoc +++ b/doc/qtcreator/src/cmake/creator-projects-cmake-presets.qdoc @@ -57,12 +57,26 @@ }, "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,8 +107,17 @@ }, "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" + } + } ] } \endcode @@ -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 /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, diff --git a/doc/qtcreator/src/cmake/creator-projects-cmake.qdoc b/doc/qtcreator/src/cmake/creator-projects-cmake.qdoc index ace6f693895..5fdbd09dd8e 100644 --- a/doc/qtcreator/src/cmake/creator-projects-cmake.qdoc +++ b/doc/qtcreator/src/cmake/creator-projects-cmake.qdoc @@ -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} diff --git a/doc/qtcreator/src/cmake/creator-projects-settings-cmake.qdoc b/doc/qtcreator/src/cmake/creator-projects-settings-cmake.qdoc new file mode 100644 index 00000000000..24f65674e30 --- /dev/null +++ b/doc/qtcreator/src/cmake/creator-projects-settings-cmake.qdoc @@ -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} +*/ diff --git a/doc/qtcreator/src/conan/creator-projects-conan.qdoc b/doc/qtcreator/src/conan/creator-projects-conan.qdoc index 0e7229ba7c3..67cdd9141ae 100644 --- a/doc/qtcreator/src/conan/creator-projects-conan.qdoc +++ b/doc/qtcreator/src/conan/creator-projects-conan.qdoc @@ -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} */ diff --git a/doc/qtcreator/src/editors/creator-only/creator-language-server.qdoc b/doc/qtcreator/src/editors/creator-only/creator-language-server.qdoc index 8d82c2a52a9..281201fb300 100644 --- a/doc/qtcreator/src/editors/creator-only/creator-language-server.qdoc +++ b/doc/qtcreator/src/editors/creator-only/creator-language-server.qdoc @@ -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} diff --git a/doc/qtcreator/src/projects/creator-only/creator-projects-settings-overview.qdoc b/doc/qtcreator/src/projects/creator-only/creator-projects-settings-overview.qdoc index 75544e47e80..73723857773 100644 --- a/doc/qtcreator/src/projects/creator-only/creator-projects-settings-overview.qdoc +++ b/doc/qtcreator/src/projects/creator-only/creator-projects-settings-overview.qdoc @@ -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 diff --git a/doc/qtcreator/src/projects/creator-only/creator-projects-settings-sharing.qdoc b/doc/qtcreator/src/projects/creator-only/creator-projects-settings-sharing.qdoc index 3e48923ad36..09898e8f56e 100644 --- a/doc/qtcreator/src/projects/creator-only/creator-projects-settings-sharing.qdoc +++ b/doc/qtcreator/src/projects/creator-only/creator-projects-settings-sharing.qdoc @@ -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 + + + + + ProjectExplorer.Project.PluginSettings + + + false + false + false + false + true + false + false + true + + + + + Version + 22 + + + \endcode + + For more information about the settings, see + \l {Override CMake settings for a project}. + \sa {Configuring Projects}, {CMake Presets} */ diff --git a/qbs/imports/QtcLuaPlugin.qbs b/qbs/imports/QtcLuaPlugin.qbs deleted file mode 100644 index 1684590480c..00000000000 --- a/qbs/imports/QtcLuaPlugin.qbs +++ /dev/null @@ -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 - } -} diff --git a/qt_attributions.json b/qt_attributions.json index 56e4fe0595c..74bd2cae83f 100644 --- a/qt_attributions.json +++ b/qt_attributions.json @@ -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" } ] diff --git a/share/qtcreator/CMakeLists.txt b/share/qtcreator/CMakeLists.txt index 73a0837ede2..6a18147f9fd 100644 --- a/share/qtcreator/CMakeLists.txt +++ b/share/qtcreator/CMakeLists.txt @@ -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 diff --git a/share/qtcreator/debugger/cdbbridge.py b/share/qtcreator/debugger/cdbbridge.py index 0b53baf1661..347d2f89c9e 100644 --- a/share/qtcreator/debugger/cdbbridge.py +++ b/share/qtcreator/debugger/cdbbridge.py @@ -85,12 +85,12 @@ class Dumper(DumperBase): del self.type_size_cache[typeid] del self.type_alignment_cache[typeid] - def enumValue(self, nativeValue): + def enumValue(self, nativeValue: cdbext.Value) -> str: val = nativeValue.nativeDebuggerValue() # remove '0n' decimal prefix of the native cdb value output return val.replace('(0n', '(') - def fromNativeValue(self, nativeValue): + def fromNativeValue(self, nativeValue: cdbext.Value) -> DumperBase.Value: self.check(isinstance(nativeValue, cdbext.Value)) val = self.Value(self) val.name = nativeValue.name() @@ -133,7 +133,7 @@ class Dumper(DumperBase): val.lbitsize = nativeValue.bitsize() return val - def nativeTypeId(self, nativeType): + def nativeTypeId(self, nativeType: cdbext.Type) -> str: self.check(isinstance(nativeType, cdbext.Type)) name = nativeType.name() if name is None or len(name) == 0: @@ -148,7 +148,7 @@ class Dumper(DumperBase): for f in nativeType.fields()]) return typeId - def from_native_type(self, nativeType): + def from_native_type(self, nativeType: cdbext.Type) -> str: self.check(isinstance(nativeType, cdbext.Type)) typeid = self.typeid_for_string(self.nativeTypeId(nativeType)) self.type_nativetype_cache[typeid] = nativeType @@ -187,7 +187,7 @@ class Dumper(DumperBase): self.nativeTypeEnumDisplay(nativeType, intval, form) return typeid - def listNativeValueChildren(self, nativeValue, include_bases): + def listNativeValueChildren(self, nativeValue: cdbext.Value, include_bases: bool) -> list[DumperBase.Value]: fields = [] index = 0 nativeMember = nativeValue.childFromIndex(index) @@ -202,19 +202,19 @@ class Dumper(DumperBase): nativeMember = nativeValue.childFromIndex(index) return fields - def listValueChildren(self, value, include_bases=True): + def listValueChildren(self, value: DumperBase.Value, include_bases=True) -> list[DumperBase.Value]: nativeValue = value.nativeValue if nativeValue is None: nativeValue = cdbext.createValue(value.address(), self.lookupNativeType(value.type.name, 0)) return self.listNativeValueChildren(nativeValue, include_bases) - def nativeListMembers(self, value, native_type, include_bases): + def nativeListMembers(self, value: DumperBase.Value, native_type: cdbext.Type, include_bases: bool) -> list[DumperBase.Value]: nativeValue = value.nativeValue if nativeValue is None: nativeValue = cdbext.createValue(value.address(), native_type) return self.listNativeValueChildren(nativeValue, include_bases) - def nativeStructAlignment(self, nativeType): + def nativeStructAlignment(self, nativeType: cdbext.Type) -> int: #DumperBase.warn("NATIVE ALIGN FOR %s" % nativeType.name) def handleItem(nativeFieldType, align): a = self.type_alignment(self.from_native_type(nativeFieldType)) @@ -224,13 +224,13 @@ class Dumper(DumperBase): align = handleItem(f.type(), align) return align - def nativeTypeEnumDisplay(self, nativeType, intval, form): + def nativeTypeEnumDisplay(self, nativeType: cdbext.Type, intval: int, form) -> str: value = self.nativeParseAndEvaluate('(%s)%d' % (nativeType.name(), intval)) if value is None: return '' return self.enumValue(value) - def enumExpression(self, enumType, enumValue): + def enumExpression(self, enumType: str, enumValue: str) -> str: ns = self.qtNamespace() return ns + "Qt::" + enumType + "(" \ + ns + "Qt::" + enumType + "::" + enumValue + ")" @@ -238,25 +238,25 @@ class Dumper(DumperBase): def pokeValue(self, typeName, *args): return None - def parseAndEvaluate(self, exp): + def parseAndEvaluate(self, exp: str) -> DumperBase.Value: return self.fromNativeValue(self.nativeParseAndEvaluate(exp)) - def nativeParseAndEvaluate(self, exp): + def nativeParseAndEvaluate(self, exp: str) -> cdbext.Value: return cdbext.parseAndEvaluate(exp) - def isWindowsTarget(self): + def isWindowsTarget(self) -> bool: return True - def isQnxTarget(self): + def isQnxTarget(self) -> bool: return False - def isArmArchitecture(self): + def isArmArchitecture(self) -> bool: return False - def isMsvcTarget(self): + def isMsvcTarget(self) -> bool: return True - def qtCoreModuleName(self): + def qtCoreModuleName(self) -> str: modules = cdbext.listOfModules() # first check for an exact module name match for coreName in ['Qt6Core', 'Qt6Cored', 'Qt5Cored', 'Qt5Core', 'QtCored4', 'QtCore4']: @@ -272,7 +272,7 @@ class Dumper(DumperBase): return coreName return None - def qtDeclarativeModuleName(self): + def qtDeclarativeModuleName(self) -> str: modules = cdbext.listOfModules() for declarativeModuleName in ['Qt6Qmld', 'Qt6Qml', 'Qt5Qmld', 'Qt5Qml']: if declarativeModuleName in modules: @@ -285,7 +285,7 @@ class Dumper(DumperBase): return declarativeModuleName return None - def qtHookDataSymbolName(self): + def qtHookDataSymbolName(self) -> str: hookSymbolName = 'qtHookData' coreModuleName = self.qtCoreModuleName() if coreModuleName is not None: @@ -299,7 +299,7 @@ class Dumper(DumperBase): self.qtHookDataSymbolName = lambda: hookSymbolName return hookSymbolName - def qtDeclarativeHookDataSymbolName(self): + def qtDeclarativeHookDataSymbolName(self) -> str: hookSymbolName = 'qtDeclarativeHookData' declarativeModuleName = self.qtDeclarativeModuleName() if declarativeModuleName is not None: @@ -314,7 +314,7 @@ class Dumper(DumperBase): self.qtDeclarativeHookDataSymbolName = lambda: hookSymbolName return hookSymbolName - def extractQtVersion(self): + def extractQtVersion(self) -> int: try: qtVersion = self.parseAndEvaluate( '((void**)&%s)[2]' % self.qtHookDataSymbolName()).integer() @@ -329,7 +329,7 @@ class Dumper(DumperBase): return None return qtVersion - def putVtableItem(self, address): + def putVtableItem(self, address: int): funcName = cdbext.getNameByAddress(address) if funcName is None: self.putItem(self.createPointerValue(address, 'void')) @@ -338,7 +338,7 @@ class Dumper(DumperBase): self.putType('void*') self.putAddress(address) - def putVTableChildren(self, item, itemCount): + def putVTableChildren(self, item: DumperBase.Value, itemCount: int) -> int: p = item.address() for i in range(itemCount): deref = self.extractPointer(p) @@ -350,12 +350,12 @@ class Dumper(DumperBase): p += self.ptrSize() return itemCount - def ptrSize(self): + def ptrSize(self) -> int: size = cdbext.pointerSize() self.ptrSize = lambda: size return size - def stripQintTypedefs(self, typeName): + def stripQintTypedefs(self, typeName: str) -> str: if typeName.startswith('qint'): prefix = '' size = typeName[4:] @@ -375,7 +375,7 @@ class Dumper(DumperBase): else: return typeName - def lookupNativeType(self, name, module=0): + def lookupNativeType(self, name: str, module=0) -> cdbext.Type: if name.startswith('void'): return FakeVoidType(name, self) return cdbext.lookupType(name, module) @@ -383,13 +383,13 @@ class Dumper(DumperBase): def reportResult(self, result, args): cdbext.reportResult('result={%s}' % result) - def readRawMemory(self, address, size): + def readRawMemory(self, address: int, size: int) -> int: mem = cdbext.readRawMemory(address, size) if len(mem) != size: raise Exception("Invalid memory request: %d bytes from 0x%x" % (size, address)) return mem - def findStaticMetaObject(self, type): + def findStaticMetaObject(self, type: DumperBase.Type) -> int: ptr = 0 if type.moduleName is not None: # Try to find the static meta object in the same module as the type definition. This is @@ -449,13 +449,10 @@ class Dumper(DumperBase): def report(self, stuff): sys.stdout.write(stuff + "\n") - def findValueByExpression(self, exp): - return cdbext.parseAndEvaluate(exp) - - def nativeValueDereferenceReference(self, value): + def nativeValueDereferenceReference(self, value: DumperBase.Value) -> DumperBase.Value: return self.nativeValueDereferencePointer(value) - def nativeValueDereferencePointer(self, value): + def nativeValueDereferencePointer(self, value: DumperBase.Value) -> DumperBase.Value: def nativeVtCastValue(nativeValue): # If we have a pointer to a derived instance of the pointer type cdb adds a # synthetic '__vtcast_' 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() diff --git a/share/qtcreator/debugger/cdbext.pyi b/share/qtcreator/debugger/cdbext.pyi new file mode 100644 index 00000000000..27a3538cfe9 --- /dev/null +++ b/share/qtcreator/debugger/cdbext.pyi @@ -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 : ... diff --git a/share/qtcreator/debugger/qttypes.py b/share/qtcreator/debugger/qttypes.py index 004779e06a2..9f2f1354ce2 100644 --- a/share/qtcreator/debugger/qttypes.py +++ b/share/qtcreator/debugger/qttypes.py @@ -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') diff --git a/src/plugins/luals/luals/init.lua b/share/qtcreator/lua-plugins/luals/init.lua similarity index 100% rename from src/plugins/luals/luals/init.lua rename to share/qtcreator/lua-plugins/luals/init.lua diff --git a/src/plugins/luals/luals/luals.lua b/share/qtcreator/lua-plugins/luals/luals.lua similarity index 100% rename from src/plugins/luals/luals/luals.lua rename to share/qtcreator/lua-plugins/luals/luals.lua diff --git a/src/plugins/luatests/luatests/INSPECT-LICENSE.txt b/share/qtcreator/lua-plugins/luatests/INSPECT-LICENSE.txt similarity index 100% rename from src/plugins/luatests/luatests/INSPECT-LICENSE.txt rename to share/qtcreator/lua-plugins/luatests/INSPECT-LICENSE.txt diff --git a/src/plugins/luatests/luatests/guidemo.lua b/share/qtcreator/lua-plugins/luatests/guidemo.lua similarity index 100% rename from src/plugins/luatests/luatests/guidemo.lua rename to share/qtcreator/lua-plugins/luatests/guidemo.lua diff --git a/src/plugins/luatests/luatests/inspect.lua b/share/qtcreator/lua-plugins/luatests/inspect.lua similarity index 100% rename from src/plugins/luatests/luatests/inspect.lua rename to share/qtcreator/lua-plugins/luatests/inspect.lua diff --git a/src/plugins/luatests/luatests/luatests.lua b/share/qtcreator/lua-plugins/luatests/luatests.lua similarity index 100% rename from src/plugins/luatests/luatests/luatests.lua rename to share/qtcreator/lua-plugins/luatests/luatests.lua diff --git a/src/plugins/luatests/luatests/qtctest.lua b/share/qtcreator/lua-plugins/luatests/qtctest.lua similarity index 100% rename from src/plugins/luatests/luatests/qtctest.lua rename to share/qtcreator/lua-plugins/luatests/qtctest.lua diff --git a/src/plugins/luatests/luatests/tests.lua b/share/qtcreator/lua-plugins/luatests/tests.lua similarity index 100% rename from src/plugins/luatests/luatests/tests.lua rename to share/qtcreator/lua-plugins/luatests/tests.lua diff --git a/src/plugins/luatests/luatests/tst_aspectcontainer.lua b/share/qtcreator/lua-plugins/luatests/tst_aspectcontainer.lua similarity index 100% rename from src/plugins/luatests/luatests/tst_aspectcontainer.lua rename to share/qtcreator/lua-plugins/luatests/tst_aspectcontainer.lua diff --git a/src/plugins/luatests/luatests/tst_fetch.lua b/share/qtcreator/lua-plugins/luatests/tst_fetch.lua similarity index 100% rename from src/plugins/luatests/luatests/tst_fetch.lua rename to share/qtcreator/lua-plugins/luatests/tst_fetch.lua diff --git a/src/plugins/luatests/luatests/tst_utils.lua b/share/qtcreator/lua-plugins/luatests/tst_utils.lua similarity index 100% rename from src/plugins/luatests/luatests/tst_utils.lua rename to share/qtcreator/lua-plugins/luatests/tst_utils.lua diff --git a/src/plugins/rustls/rustls/init.lua b/share/qtcreator/lua-plugins/rustls/init.lua similarity index 100% rename from src/plugins/rustls/rustls/init.lua rename to share/qtcreator/lua-plugins/rustls/init.lua diff --git a/src/plugins/rustls/rustls/rustls.lua b/share/qtcreator/lua-plugins/rustls/rustls.lua similarity index 100% rename from src/plugins/rustls/rustls/rustls.lua rename to share/qtcreator/lua-plugins/rustls/rustls.lua diff --git a/src/plugins/tellajoke/tellajoke/tellajoke.lua b/share/qtcreator/lua-plugins/tellajoke/tellajoke.lua similarity index 100% rename from src/plugins/tellajoke/tellajoke/tellajoke.lua rename to share/qtcreator/lua-plugins/tellajoke/tellajoke.lua diff --git a/share/qtcreator/translations/qtcreator_de.ts b/share/qtcreator/translations/qtcreator_de.ts index 3dc80d58d94..cc2c1327d9e 100644 --- a/share/qtcreator/translations/qtcreator_de.ts +++ b/share/qtcreator/translations/qtcreator_de.ts @@ -21936,8 +21936,14 @@ Doppelklicken Sie einen Eintrag um ihn zu ändern. Executable: + adjective Ausführbar: + + Executable: + noun + Ausführbare Datei: + Symbolic link: Symbolischer Link: diff --git a/share/qtcreator/translations/qtcreator_hr.ts b/share/qtcreator/translations/qtcreator_hr.ts index acd2770cab3..93848c19411 100644 --- a/share/qtcreator/translations/qtcreator_hr.ts +++ b/share/qtcreator/translations/qtcreator_hr.ts @@ -2133,8 +2133,14 @@ Međutim, korištenje opuštenih i proširenih pravila također znači da nije m Executable: + adjective Izvršavajuća: + + Executable: + noun + Izvršna datoteka: + Symbolic link: Simbolička poveznica: diff --git a/share/qtcreator/translations/qtcreator_ru.ts b/share/qtcreator/translations/qtcreator_ru.ts index 7f57fe4f12d..44f5dfa5823 100644 --- a/share/qtcreator/translations/qtcreator_ru.ts +++ b/share/qtcreator/translations/qtcreator_ru.ts @@ -18313,8 +18313,14 @@ will also disable the following plugins: Executable: + adjective Можно запускать: + + Executable: + noun + Программа: + Symbolic link: Символьная ссылка: diff --git a/share/share.qbs b/share/share.qbs index 2a1c8d8fce4..745a8131a94 100644 --- a/share/share.qbs +++ b/share/share.qbs @@ -17,6 +17,7 @@ Product { "designer/**/*", "glsl/**/*", "jsonschemas/**/*", + "lua-plugins/**/*", "modeleditor/**/*", "qml/**/*", "qmldesigner/**/*", diff --git a/src/app/main.cpp b/src/app/main.cpp index 86c9106a565..4ec11d5e896 100644 --- a/src/app/main.cpp +++ b/src/app/main.cpp @@ -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: /plugins/ // where is e.g. // "%LOCALAPPDATA%\QtProject\qtcreator" on Windows Vista and later diff --git a/src/libs/utils/devicefileaccess.cpp b/src/libs/utils/devicefileaccess.cpp index 303ffa6bf50..c8f920c07f7 100644 --- a/src/libs/utils/devicefileaccess.cpp +++ b/src/libs/utils/devicefileaccess.cpp @@ -17,9 +17,11 @@ #endif #include +#include #include #include #include +#include #include #include @@ -33,7 +35,6 @@ #include #endif -#include #include #include @@ -389,6 +390,13 @@ expected_str DeviceFileAccess::createTempFile(const FilePath &filePath Tr::tr("createTempFile is not implemented for \"%1\".").arg(filePath.toUserOutput())); } +Utils::expected_str> 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 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> DesktopDeviceFileAccess::watch( + const FilePath &path) const +{ + return std::make_unique(path); +} + QDateTime DesktopDeviceFileAccess::lastModified(const FilePath &filePath) const { return QFileInfo(filePath.path()).lastModified(); diff --git a/src/libs/utils/devicefileaccess.h b/src/libs/utils/devicefileaccess.h index 8a0884ec1d0..451fb2db4be 100644 --- a/src/libs/utils/devicefileaccess.h +++ b/src/libs/utils/devicefileaccess.h @@ -72,6 +72,8 @@ protected: const QByteArray &data) const; virtual expected_str createTempFile(const FilePath &filePath); + + virtual Utils::expected_str> watch(const FilePath &path) const; }; class QTCREATOR_UTILS_EXPORT DesktopDeviceFileAccess : public DeviceFileAccess @@ -128,6 +130,7 @@ protected: expected_str createTempFile(const FilePath &filePath) override; + Utils::expected_str> watch(const FilePath &path) const override; }; class QTCREATOR_UTILS_EXPORT UnixDeviceFileAccess : public DeviceFileAccess diff --git a/src/libs/utils/filepath.cpp b/src/libs/utils/filepath.cpp index c4d77a29efc..23a6ff24129 100644 --- a/src/libs/utils/filepath.cpp +++ b/src/libs/utils/filepath.cpp @@ -313,6 +313,11 @@ bool FilePath::equalsCaseSensitive(const FilePath &other) const return equals(*this, other, Qt::CaseSensitive); } +Utils::expected_str> FilePath::watch() const +{ + return fileAccess()->watch(*this); +} + /*! Returns a QString for passing on to QString based APIs. diff --git a/src/libs/utils/filepath.h b/src/libs/utils/filepath.h index e742bf1a0de..d1845571203 100644 --- a/src/libs/utils/filepath.h +++ b/src/libs/utils/filepath.h @@ -55,6 +55,16 @@ public: using FilePaths = QList; +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> watch() const; + private: // These are needed. QTCREATOR_UTILS_EXPORT friend bool operator==(const FilePath &first, const FilePath &second); diff --git a/src/libs/utils/namevaluesdialog.cpp b/src/libs/utils/namevaluesdialog.cpp index 5a45c54a75e..cd34a23955f 100644 --- a/src/libs/utils/namevaluesdialog.cpp +++ b/src/libs/utils/namevaluesdialog.cpp @@ -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) { diff --git a/src/libs/utils/namevaluesdialog.h b/src/libs/utils/namevaluesdialog.h index a1e884fe5b5..abf6b84b23e 100644 --- a/src/libs/utils/namevaluesdialog.h +++ b/src/libs/utils/namevaluesdialog.h @@ -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); diff --git a/src/libs/utils/osspecificaspects.h b/src/libs/utils/osspecificaspects.h index 239290faec7..0af8ad52102 100644 --- a/src/libs/utils/osspecificaspects.h +++ b/src/libs/utils/osspecificaspects.h @@ -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; } diff --git a/src/libs/utils/pathchooser.cpp b/src/libs/utils/pathchooser.cpp index 9b2177fedb6..8e941f52a34 100644 --- a/src/libs/utils/pathchooser.cpp +++ b/src/libs/utils/pathchooser.cpp @@ -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 diff --git a/src/libs/utils/pathchooser.h b/src/libs/utils/pathchooser.h index a3e259a748d..b0d70e90b8f 100644 --- a/src/libs/utils/pathchooser.h +++ b/src/libs/utils/pathchooser.h @@ -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); diff --git a/src/plugins/CMakeLists.txt b/src/plugins/CMakeLists.txt index a0bfe5b1cfc..423b17d9284 100644 --- a/src/plugins/CMakeLists.txt +++ b/src/plugins/CMakeLists.txt @@ -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) diff --git a/src/plugins/android/androidbuildapkstep.cpp b/src/plugins/android/androidbuildapkstep.cpp index 51f73180971..3ad6a4ba849 100644 --- a/src/plugins/android/androidbuildapkstep.cpp +++ b/src/plugins/android/androidbuildapkstep.cpp @@ -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()) diff --git a/src/plugins/android/createandroidmanifestwizard.cpp b/src/plugins/android/createandroidmanifestwizard.cpp index 8f50666419a..18a7872e08d 100644 --- a/src/plugins/android/createandroidmanifestwizard.cpp +++ b/src/plugins/android/createandroidmanifestwizard.cpp @@ -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()) { diff --git a/src/plugins/clangtools/diagnosticmark.cpp b/src/plugins/clangtools/diagnosticmark.cpp index 90b4e19812d..5ea0895b947 100644 --- a/src/plugins/clangtools/diagnosticmark.cpp +++ b/src/plugins/clangtools/diagnosticmark.cpp @@ -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() diff --git a/src/plugins/clangtools/settingswidget.cpp b/src/plugins/clangtools/settingswidget.cpp index 113373f57e0..4b686e61ac9 100644 --- a/src/plugins/clangtools/settingswidget.cpp +++ b/src/plugins/clangtools/settingswidget.cpp @@ -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 diff --git a/src/plugins/clearcase/settingspage.cpp b/src/plugins/clearcase/settingspage.cpp index 010d3d1e98e..713ef78c344 100644 --- a/src/plugins/clearcase/settingspage.cpp +++ b/src/plugins/clearcase/settingspage.cpp @@ -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(); diff --git a/src/plugins/cmakeprojectmanager/cmakebuildsystem.cpp b/src/plugins/cmakeprojectmanager/cmakebuildsystem.cpp index 13aee2f2de9..e0d2b6773fb 100644 --- a/src/plugins/cmakeprojectmanager/cmakebuildsystem.cpp +++ b/src/plugins/cmakeprojectmanager/cmakebuildsystem.cpp @@ -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 CMakeBuildSystem::appTargets() const { + const CMakeConfig &cm = configurationFromCMake(); + QString emulator = cm.stringValueOf("CMAKE_CROSSCOMPILING_EMULATOR"); + QList appTargetList; const bool forAndroid = DeviceTypeKitAspect::deviceTypeId(kit()) == Android::Constants::ANDROID_DEVICE_TYPE; @@ -1989,6 +1992,15 @@ const QList 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; diff --git a/src/plugins/cmakeprojectmanager/cmakebuildtarget.h b/src/plugins/cmakeprojectmanager/cmakebuildtarget.h index d40729a3970..934070bdfd1 100644 --- a/src/plugins/cmakeprojectmanager/cmakebuildtarget.h +++ b/src/plugins/cmakeprojectmanager/cmakebuildtarget.h @@ -7,6 +7,7 @@ #include #include +#include #include @@ -30,6 +31,7 @@ class CMAKE_EXPORT CMakeBuildTarget public: QString title; Utils::FilePath executable; // TODO: rename to output? + QList launchers; TargetType targetType = UtilityType; bool linksToQtGui = false; bool qtcRunnable = true; diff --git a/src/plugins/cmakeprojectmanager/configmodelitemdelegate.cpp b/src/plugins/cmakeprojectmanager/configmodelitemdelegate.cpp index c8db1a85cb6..d9e7a943c3d 100644 --- a/src/plugins/cmakeprojectmanager/configmodelitemdelegate.cpp +++ b/src/plugins/cmakeprojectmanager/configmodelitemdelegate.cpp @@ -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(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(editor); diff --git a/src/plugins/cmakeprojectmanager/fileapidataextractor.cpp b/src/plugins/cmakeprojectmanager/fileapidataextractor.cpp index 6f4050a3aa4..7a6de1749de 100644 --- a/src/plugins/cmakeprojectmanager/fileapidataextractor.cpp +++ b/src/plugins/cmakeprojectmanager/fileapidataextractor.cpp @@ -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; } diff --git a/src/plugins/cmakeprojectmanager/fileapiparser.cpp b/src/plugins/cmakeprojectmanager/fileapiparser.cpp index d404d124db8..d9ea457600f 100644 --- a/src/plugins/cmakeprojectmanager/fileapiparser.cpp +++ b/src/plugins/cmakeprojectmanager/fileapiparser.cpp @@ -11,6 +11,7 @@ #include #include +#include #include #include @@ -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(launchers, [](const QJsonValue &v) { + const QJsonObject o = v.toObject(); + QList 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; } diff --git a/src/plugins/cmakeprojectmanager/fileapiparser.h b/src/plugins/cmakeprojectmanager/fileapiparser.h index 9043d38c260..f6a59edae2a 100644 --- a/src/plugins/cmakeprojectmanager/fileapiparser.h +++ b/src/plugins/cmakeprojectmanager/fileapiparser.h @@ -197,6 +197,7 @@ public: QList artifacts; QString installPrefix; std::vector installDestination; + QList launcherInfos; std::optional link; std::optional archive; std::vector dependencies; diff --git a/src/plugins/coreplugin/dialogs/externaltoolconfig.cpp b/src/plugins/coreplugin/dialogs/externaltoolconfig.cpp index 76ff935975d..2141ef61c2e 100644 --- a/src/plugins/coreplugin/dialogs/externaltoolconfig.cpp +++ b/src/plugins/coreplugin/dialogs/externaltoolconfig.cpp @@ -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())); diff --git a/src/plugins/coreplugin/dialogs/filepropertiesdialog.cpp b/src/plugins/coreplugin/dialogs/filepropertiesdialog.cpp index de3362a408f..2a480ff17b5 100644 --- a/src/plugins/coreplugin/dialogs/filepropertiesdialog.cpp +++ b/src/plugins/coreplugin/dialogs/filepropertiesdialog.cpp @@ -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 diff --git a/src/plugins/coreplugin/locator/spotlightlocatorfilter.cpp b/src/plugins/coreplugin/locator/spotlightlocatorfilter.cpp index d8f07178b43..bcc685c9532 100644 --- a/src/plugins/coreplugin/locator/spotlightlocatorfilter.cpp +++ b/src/plugins/coreplugin/locator/spotlightlocatorfilter.cpp @@ -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(); diff --git a/src/plugins/debugger/dap/dapclient.cpp b/src/plugins/debugger/dap/dapclient.cpp index b67d7ec4754..c7839d55822 100644 --- a/src/plugins/debugger/dap/dapclient.cpp +++ b/src/plugins/debugger/dap/dapclient.cpp @@ -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; diff --git a/src/plugins/debugger/dap/dapclient.h b/src/plugins/debugger/dap/dapclient.h index f4c3df2ef3a..268e1e1f37f 100644 --- a/src/plugins/debugger/dap/dapclient.h +++ b/src/plugins/debugger/dap/dapclient.h @@ -55,6 +55,7 @@ enum class DapResponseType SetBreakpoints, SetFunctionBreakpoints, Attach, + Launch, Unknown }; diff --git a/src/plugins/debugger/dap/dapengine.cpp b/src/plugins/debugger/dap/dapengine.cpp index e311bb36822..da659921c2e 100644 --- a/src/plugins/debugger/dap/dapengine.cpp +++ b/src/plugins/debugger/dap/dapengine.cpp @@ -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; diff --git a/src/plugins/debugger/dap/lldbdapengine.cpp b/src/plugins/debugger/dap/lldbdapengine.cpp index 4dc38ca857e..8dfd75a75b2 100644 --- a/src/plugins/debugger/dap/lldbdapengine.cpp +++ b/src/plugins/debugger/dap/lldbdapengine.cpp @@ -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{ - {"noDebug", false}, - {"program", rp.inferior.command.executable().path()}, - {"args", rp.inferior.command.arguments()}, - {"cwd", rp.inferior.workingDirectory.path()}, - {"sourceMap", sourceMap()}, - {"preRunCommands", preRunCommands()}, - {"__restart", ""}, - }); + const QJsonArray env = environment(); + QJsonObject launchJson{ + {"noDebug", false}, + {"program", rp.inferior.command.executable().path()}, + {"args", rp.inferior.command.arguments()}, + {"cwd", rp.inferior.workingDirectory.path()}, + {"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{ - {"program", rp.inferior.command.executable().path()}, - {"pid", QString::number(rp.attachPID.pid())}, - {"sourceMap", sourceMap()}, - {"preRunCommands", preRunCommands()}, - {"__restart", ""}, - }); + QJsonObject attachJson{ + {"program", rp.inferior.command.executable().path()}, + {"pid", QString::number(rp.attachPID.pid())}, + {"__restart", ""}, + }; + if (!map.isEmpty()) + attachJson.insert("sourceMap", map); + if (!commands.isEmpty()) + attachJson.insert("preRunCommands", commands); + + m_dapClient->postRequest("attach", attachJson); qCDebug(logCategory()) << "handleDapAttach"; } diff --git a/src/plugins/debugger/dap/lldbdapengine.h b/src/plugins/debugger/dap/lldbdapengine.h index 0ebeb2d2ee1..f4f59903820 100644 --- a/src/plugins/debugger/dap/lldbdapengine.h +++ b/src/plugins/debugger/dap/lldbdapengine.h @@ -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; }; diff --git a/src/plugins/debugger/debuggersourcepathmappingwidget.cpp b/src/plugins/debugger/debuggersourcepathmappingwidget.cpp index 98b84e2020e..e8f231473b2 100644 --- a/src/plugins/debugger/debuggersourcepathmappingwidget.cpp +++ b/src/plugins/debugger/debuggersourcepathmappingwidget.cpp @@ -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) diff --git a/src/plugins/debugger/loadcoredialog.cpp b/src/plugins/debugger/loadcoredialog.cpp index 4c006199700..937c77b8e19 100644 --- a/src/plugins/debugger/loadcoredialog.cpp +++ b/src/plugins/debugger/loadcoredialog.cpp @@ -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); diff --git a/src/plugins/docker/dockerapi.cpp b/src/plugins/docker/dockerapi.cpp index ea62fd88113..ccfaaf104c3 100644 --- a/src/plugins/docker/dockerapi.cpp +++ b/src/plugins/docker/dockerapi.cpp @@ -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) { diff --git a/src/plugins/docker/dockerapi.h b/src/plugins/docker/dockerapi.h index 3e697654a3a..87301a98d1a 100644 --- a/src/plugins/docker/dockerapi.h +++ b/src/plugins/docker/dockerapi.h @@ -44,6 +44,8 @@ public: static void recheckDockerDaemon(); QFuture>> networks(); + bool isContainerRunning(const QString &containerId); + signals: void dockerDaemonAvailableChanged(); diff --git a/src/plugins/haskell/haskellbuildconfiguration.cpp b/src/plugins/haskell/haskellbuildconfiguration.cpp index 1434833ff65..bb8ef948705 100644 --- a/src/plugins/haskell/haskellbuildconfiguration.cpp +++ b/src/plugins/haskell/haskellbuildconfiguration.cpp @@ -90,7 +90,7 @@ public: &Utils::PathChooser::textChanged, bc, [bc, buildDirectoryInput](const QString &) { - bc->setBuildDirectory(buildDirectoryInput->rawFilePath()); + bc->setBuildDirectory(buildDirectoryInput->unexpandedFilePath()); }); } }; diff --git a/src/plugins/incredibuild/commandbuilderaspect.cpp b/src/plugins/incredibuild/commandbuilderaspect.cpp index 38d0d858e8e..83476af36ff 100644 --- a/src/plugins/incredibuild/commandbuilderaspect.cpp +++ b/src/plugins/incredibuild/commandbuilderaspect.cpp @@ -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(); }); } diff --git a/src/plugins/lua/lua.qbs b/src/plugins/lua/lua.qbs index 2a539bb0b4d..d4402c25ee3 100644 --- a/src/plugins/lua/lua.qbs +++ b/src/plugins/lua/lua.qbs @@ -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" } diff --git a/src/plugins/lua/luaengine.cpp b/src/plugins/lua/luaengine.cpp index 29ca17fad6e..abfc78957b1 100644 --- a/src/plugins/lua/luaengine.cpp +++ b/src/plugins/lua/luaengine.cpp @@ -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)); } diff --git a/src/plugins/lua/luaengine.h b/src/plugins/lua/luaengine.h index f8fa085d6d0..7c8bbda7c89 100644 --- a/src/plugins/lua/luaengine.h +++ b/src/plugins/lua/luaengine.h @@ -51,7 +51,7 @@ protected: public: using PackageProvider = std::function; - ~LuaEngine(); + ~LuaEngine() override; static LuaEngine &instance(); Utils::expected_str loadPlugin(const Utils::FilePath &path); diff --git a/src/plugins/lua/luapluginspec.cpp b/src/plugins/lua/luapluginspec.cpp index 4d0e9d76708..3e6b1eb3edd 100644 --- a/src/plugins/lua/luapluginspec.cpp +++ b/src/plugins/lua/luapluginspec.cpp @@ -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 { diff --git a/src/plugins/lua/wizards/plugin/icon.png b/src/plugins/lua/wizards/plugin/icon.png new file mode 100644 index 00000000000..11ccac86ddd Binary files /dev/null and b/src/plugins/lua/wizards/plugin/icon.png differ diff --git a/src/plugins/lua/wizards/plugin/icon@2x.png b/src/plugins/lua/wizards/plugin/icon@2x.png new file mode 100644 index 00000000000..49a2ad834e9 Binary files /dev/null and b/src/plugins/lua/wizards/plugin/icon@2x.png differ diff --git a/src/plugins/lua/wizards/plugin/wizard.json b/src/plugins/lua/wizards/plugin/wizard.json index 4846fdfccb3..078ac900918 100644 --- a/src/plugins/lua/wizards/plugin/wizard.json +++ b/src/plugins/lua/wizards/plugin/wizard.json @@ -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": [ { diff --git a/src/plugins/lua/wizards/wizards.qrc b/src/plugins/lua/wizards/wizards.qrc index 098c2c3f418..076550cb4a6 100644 --- a/src/plugins/lua/wizards/wizards.qrc +++ b/src/plugins/lua/wizards/wizards.qrc @@ -7,5 +7,7 @@ plugin/project.json plugin/wizard.json plugin/.luarc.json + plugin/icon.png + plugin/icon@2x.png diff --git a/src/plugins/luals/CMakeLists.txt b/src/plugins/luals/CMakeLists.txt deleted file mode 100644 index cec9a052dee..00000000000 --- a/src/plugins/luals/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -add_qtc_lua_plugin(luals - SOURCES luals/luals.lua - luals/init.lua -) diff --git a/src/plugins/luals/luals.qbs b/src/plugins/luals/luals.qbs deleted file mode 100644 index ea05595f80a..00000000000 --- a/src/plugins/luals/luals.qbs +++ /dev/null @@ -1,8 +0,0 @@ -QtcLuaPlugin { - name: "luals" - - luafiles: [ - "init.lua", - "luals.lua", - ] -} diff --git a/src/plugins/luatests/CMakeLists.txt b/src/plugins/luatests/CMakeLists.txt deleted file mode 100644 index 0bad7da433b..00000000000 --- a/src/plugins/luatests/CMakeLists.txt +++ /dev/null @@ -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 -) diff --git a/src/plugins/luatests/luatests.qbs b/src/plugins/luatests/luatests.qbs deleted file mode 100644 index 687cd6579bd..00000000000 --- a/src/plugins/luatests/luatests.qbs +++ /dev/null @@ -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", - ] -} diff --git a/src/plugins/mcusupport/mcupackage.cpp b/src/plugins/mcusupport/mcupackage.cpp index 2ccc4bcc1a0..20ee020ae32 100644 --- a/src/plugins/mcusupport/mcupackage.cpp +++ b/src/plugins/mcusupport/mcupackage.cpp @@ -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] { diff --git a/src/plugins/nim/project/nimtoolchain.cpp b/src/plugins/nim/project/nimtoolchain.cpp index 80036592644..701883de0c0 100644 --- a/src/plugins/nim/project/nimtoolchain.cpp +++ b/src/plugins/nim/project/nimtoolchain.cpp @@ -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(toolchain()); QTC_ASSERT(tc, return); tc->setCompilerCommand(path); diff --git a/src/plugins/plugins.qbs b/src/plugins/plugins.qbs index 820ff891224..7293d34d683 100644 --- a/src/plugins/plugins.qbs +++ b/src/plugins/plugins.qbs @@ -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", diff --git a/src/plugins/projectexplorer/buildtargetinfo.h b/src/plugins/projectexplorer/buildtargetinfo.h index 4ba1c4de5b4..c99dec64308 100644 --- a/src/plugins/projectexplorer/buildtargetinfo.h +++ b/src/plugins/projectexplorer/buildtargetinfo.h @@ -5,12 +5,15 @@ #include "projectexplorer_export.h" +#include "runconfiguration.h" + #include #include #include namespace ProjectExplorer { +class Launcher; class PROJECTEXPLORER_EXPORT BuildTargetInfo { @@ -19,6 +22,7 @@ public: QString displayName; QString displayNameUniquifier; + QList launchers; Utils::FilePath targetFilePath; Utils::FilePath projectFilePath; Utils::FilePath workingDirectory; diff --git a/src/plugins/projectexplorer/desktoprunconfiguration.cpp b/src/plugins/projectexplorer/desktoprunconfiguration.cpp index a8d3284e9be..02f31c13452 100644 --- a/src/plugins/projectexplorer/desktoprunconfiguration.cpp +++ b/src/plugins/projectexplorer/desktoprunconfiguration.cpp @@ -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->setUseTerminalHint(bti.targetFilePath.needsDevice() ? false : bti.usesTerminal); terminalAspect->setEnabled(!bti.targetFilePath.needsDevice()); + auto launcherAspect = aspect(); + 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()->setExecutable(bti.targetFilePath); aspect()->setDefaultWorkingDirectory(bti.workingDirectory); emit aspect()->environmentChanged(); diff --git a/src/plugins/projectexplorer/devicesupport/idevice.cpp b/src/plugins/projectexplorer/devicesupport/idevice.cpp index 1387f9edc44..90eca216fa7 100644 --- a/src/plugins/projectexplorer/devicesupport/idevice.cpp +++ b/src/plugins/projectexplorer/devicesupport/idevice.cpp @@ -139,6 +139,7 @@ public: IDevice::MachineType machineType = IDevice::Hardware; OsType osType = OsTypeOther; DeviceFileAccess *fileAccess = nullptr; + std::function fileAccessFactory; int version = 0; // This is used by devices that have been added by the SDK. Utils::SynchronizedValue 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 fileAccessFactory) +{ + d->fileAccessFactory = fileAccessFactory; +} + IDevice::DeviceInfo IDevice::deviceInformation() const { const QString key = Tr::tr("Device"); diff --git a/src/plugins/projectexplorer/devicesupport/idevice.h b/src/plugins/projectexplorer/devicesupport/idevice.h index b83c558e87b..490906bf901 100644 --- a/src/plugins/projectexplorer/devicesupport/idevice.h +++ b/src/plugins/projectexplorer/devicesupport/idevice.h @@ -241,6 +241,7 @@ protected: void setDisplayType(const QString &type); void setOsType(Utils::OsType osType); void setFileAccess(Utils::DeviceFileAccess *fileAccess); + void setFileAccess(std::function fileAccessFactory); private: IDevice(const IDevice &) = delete; diff --git a/src/plugins/projectexplorer/environmentaspect.cpp b/src/plugins/projectexplorer/environmentaspect.cpp index fb5aaa2c243..43107b6141d 100644 --- a/src/plugins/projectexplorer/environmentaspect.cpp +++ b/src/plugins/projectexplorer/environmentaspect.cpp @@ -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 diff --git a/src/plugins/projectexplorer/environmentaspect.h b/src/plugins/projectexplorer/environmentaspect.h index 26dd43f6a41..86d7d345008 100644 --- a/src/plugins/projectexplorer/environmentaspect.h +++ b/src/plugins/projectexplorer/environmentaspect.h @@ -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; diff --git a/src/plugins/projectexplorer/environmentaspectwidget.cpp b/src/plugins/projectexplorer/environmentaspectwidget.cpp index d47b4e82cc3..148b4415658 100644 --- a/src/plugins/projectexplorer/environmentaspectwidget.cpp +++ b/src/plugins/projectexplorer/environmentaspectwidget.cpp @@ -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); diff --git a/src/plugins/projectexplorer/environmentwidget.cpp b/src/plugins/projectexplorer/environmentwidget.cpp index c438b7b1f2c..c62a9488594 100644 --- a/src/plugins/projectexplorer/environmentwidget.cpp +++ b/src/plugins/projectexplorer/environmentwidget.cpp @@ -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. diff --git a/src/plugins/projectexplorer/environmentwidget.h b/src/plugins/projectexplorer/environmentwidget.h index b1a26b036b3..f204ae978f0 100644 --- a/src/plugins/projectexplorer/environmentwidget.h +++ b/src/plugins/projectexplorer/environmentwidget.h @@ -38,6 +38,8 @@ public: void expand(); + void forceUpdateCheck() const; + signals: void userChangesChanged(); void detailsVisibleChanged(bool visible); diff --git a/src/plugins/projectexplorer/projectnodeshelper.h b/src/plugins/projectexplorer/projectnodeshelper.h index 24edc853165..37b015ec321 100644 --- a/src/plugins/projectexplorer/projectnodeshelper.h +++ b/src/plugins/projectexplorer/projectnodeshelper.h @@ -29,8 +29,8 @@ struct DirectoryScanResult static DirectoryScanResult scanForFiles( const QFuture &future, const Utils::FilePath &directory, - const QDir::Filters &filter, - const std::function factory, + QDir::Filters filter, + const std::function &factory, const QList &versionControls) { DirectoryScanResult result; @@ -57,10 +57,10 @@ static DirectoryScanResult scanForFiles( template QList scanForFilesRecursively( QPromise &promise, - double progressRange, + int progressRange, const Utils::FilePath &directory, - const QDir::Filters &filter, - const std::function factory, + QDir::Filters filter, + const std::function &factory, const QList &versionControls) { const QFuture future(promise.future()); @@ -69,10 +69,9 @@ QList scanForFilesRecursively( const DirectoryScanResult result = scanForFiles(future, directory, filter, factory, versionControls); QList fileNodes = result.nodes; - const double progressIncrement = progressRange - / static_cast( - fileNodes.count() + result.subDirectories.count()); - promise.setProgressValue(fileNodes.count() * progressIncrement); + const int progressIncrement = int( + progressRange / static_cast(fileNodes.count() + result.subDirectories.count())); + promise.setProgressValue(int(fileNodes.count() * progressIncrement)); QList> subDirectories; auto addSubDirectories = [&](const Utils::FilePaths &subdirs, int progressIncrement) { for (const Utils::FilePath &subdir : subdirs) { @@ -98,12 +97,13 @@ QList scanForFilesRecursively( const int progressRange = iterator->second; const DirectoryScanResult result = task.result(); fileNodes.append(result.nodes); - const int subDirCount = result.subDirectories.count(); + const qsizetype subDirCount = result.subDirectories.count(); if (subDirCount == 0) { promise.setProgressValue(promise.future().progressValue() + progressRange); } else { - const int fileCount = result.nodes.count(); - const int increment = progressRange / static_cast(fileCount + subDirCount); + const qsizetype fileCount = result.nodes.count(); + const int increment = int( + progressRange / static_cast(fileCount + subDirCount)); promise.setProgressValue( promise.future().progressValue() + increment * fileCount); addSubDirectories(result.subDirectories, increment); @@ -126,12 +126,12 @@ template QList scanForFiles( QPromise &promise, const Utils::FilePath &directory, - const QDir::Filters &filter, - const std::function factory) + QDir::Filters filter, + const std::function &factory) { promise.setProgressRange(0, 1000000); return Internal::scanForFilesRecursively(promise, - 1000000.0, + 1000000, directory, filter, factory, diff --git a/src/plugins/projectexplorer/runconfiguration.cpp b/src/plugins/projectexplorer/runconfiguration.cpp index 97d467fbc75..3c78b37cc44 100644 --- a/src/plugins/projectexplorer/runconfiguration.cpp +++ b/src/plugins/projectexplorer/runconfiguration.cpp @@ -71,7 +71,7 @@ void GlobalOrProjectAspect::setProjectSettings(AspectContainer *settings) void GlobalOrProjectAspect::setGlobalSettings(AspectContainer *settings) { m_globalSettings = settings; - m_projectSettings->setAutoApply(false); + m_globalSettings->setAutoApply(false); } void GlobalOrProjectAspect::setUsingGlobalSettings(bool value) @@ -173,6 +173,9 @@ RunConfiguration::RunConfiguration(Target *target, Utils::Id id) m_commandLineGetter = [this] { + Launcher launcher; + if (const auto launcherAspect = aspect()) + launcher = launcherAspect->currentLauncher(); FilePath executable; if (const auto executableAspect = aspect()) executable = executableAspect->executable(); @@ -180,7 +183,14 @@ RunConfiguration::RunConfiguration(Target *target, Utils::Id id) if (const auto argumentsAspect = aspect()) arguments = argumentsAspect->arguments(); - return CommandLine{executable, arguments, CommandLine::Raw}; + if (launcher.command.isEmpty()) + return CommandLine{executable, arguments, CommandLine::Raw}; + + CommandLine launcherCommand(launcher.command, launcher.arguments); + launcherCommand.addArg(executable.toString()); + launcherCommand.addArgs(arguments, CommandLine::Raw); + + return launcherCommand; }; } diff --git a/src/plugins/projectexplorer/runconfiguration.h b/src/plugins/projectexplorer/runconfiguration.h index 2054a840c14..b49ad3e7d77 100644 --- a/src/plugins/projectexplorer/runconfiguration.h +++ b/src/plugins/projectexplorer/runconfiguration.h @@ -28,6 +28,51 @@ class RunConfigurationFactory; class RunConfiguration; class RunConfigurationCreationInfo; class Target; +class BuildTargetInfo; + +/** + * Contains start program entries that are retrieved + * from the cmake file api + */ +class LauncherInfo +{ +public: + QString type; + Utils::FilePath command; + QStringList arguments; +}; + +/** + * Contains a start program entry that is displayed in the run configuration interface. + * + * This follows the design for the use of "Test Launcher", the + * Wrappers for running executables on the host system and "Emulator", + * wrappers for cross-compiled applications, which are supported for + * example by the cmake build system. + */ +class PROJECTEXPLORER_EXPORT Launcher +{ +public: + Launcher() = default; + + /// Create a single launcher from the \p launcherInfo parameter, which can be of type "Test launcher" or "Emulator" + Launcher(const LauncherInfo &launcherInfo, const Utils::FilePath &sourceDirectory); + + /// Create a combined launcher from the passed info parameters, with \p testLauncherInfo + /// as first and \p emulatorLauncherInfo appended + Launcher(const LauncherInfo &testLauncherInfo, const LauncherInfo &emulatorlauncherInfo, const Utils::FilePath &sourceDirectory); + + bool operator==(const Launcher &other) const + { + return id == other.id && displayName == other.displayName && command == other.command + && arguments == other.arguments; + } + + QString id; + QString displayName; + Utils::FilePath command; + QStringList arguments; +}; /** * An interface to facilitate switching between hunks of diff --git a/src/plugins/projectexplorer/runconfigurationaspects.cpp b/src/plugins/projectexplorer/runconfigurationaspects.cpp index a383438c8b5..6f49b61c0e8 100644 --- a/src/plugins/projectexplorer/runconfigurationaspects.cpp +++ b/src/plugins/projectexplorer/runconfigurationaspects.cpp @@ -186,7 +186,7 @@ void WorkingDirectoryAspect::addToLayout(Layout &builder) m_chooser->setBaseDirectory(m_defaultWorkingDirectory); m_chooser->setFilePath(m_workingDirectory.isEmpty() ? m_defaultWorkingDirectory : m_workingDirectory); connect(m_chooser.data(), &PathChooser::textChanged, this, [this] { - m_workingDirectory = m_chooser->rawFilePath(); + m_workingDirectory = m_chooser->unexpandedFilePath(); m_resetButton->setEnabled(m_workingDirectory != m_defaultWorkingDirectory); }); @@ -797,6 +797,156 @@ Interpreter::Interpreter(const QString &_id, , autoDetected(_autoDetected) {} +static QString launcherType2UiString(const QString &type) +{ + if (type == "test") + return Tr::tr("Test"); + else if (type == "emulator") + return Tr::tr("Emulator"); + return QString(); +} + +Launcher::Launcher(const LauncherInfo &launcherInfo, const FilePath &sourceDirectory) + : id(launcherInfo.type) + , arguments(launcherInfo.arguments) +{ + if (launcherInfo.type != "unused") { + command = launcherInfo.command; + if (command.isRelativePath()) + command = sourceDirectory.resolvePath(command); + displayName = QString("%1 (%2)").arg(launcherType2UiString(launcherInfo.type), + CommandLine(command, arguments).displayName()); + } +} + +Launcher::Launcher(const LauncherInfo &testLauncherInfo, const LauncherInfo &emulatorLauncherInfo, const Utils::FilePath &sourceDirectory) + : id(testLauncherInfo.type + " + " + emulatorLauncherInfo.type) + , command(testLauncherInfo.command) + , arguments(testLauncherInfo.arguments) +{ + if (command.isRelativePath()) + command = sourceDirectory.resolvePath(command); + FilePath command1 = emulatorLauncherInfo.command; + if (command1.isRelativePath()) + command1 = sourceDirectory.resolvePath(command1); + arguments.append(command1.toString()); + arguments.append(emulatorLauncherInfo.arguments); + displayName = QString("%1 + %2 (%3)").arg(launcherType2UiString(testLauncherInfo.type), + launcherType2UiString(emulatorLauncherInfo.type), + CommandLine(command, arguments).displayName()); +} + +/*! +\class ProjectExplorer::LauncherAspect +\inmodule QtCreator + +\brief With the LauncherAspect class, a user can specify a launcher program for +use with executable files for which a launcher program is optionally available. +*/ + +LauncherAspect::LauncherAspect(AspectContainer *container) + : BaseAspect(container) +{ + addDataExtractor(this, &LauncherAspect::currentLauncher, &Data::launcher); +} + +Launcher LauncherAspect::currentLauncher() const +{ + return Utils::findOrDefault(m_launchers, Utils::equal(&Launcher::id, m_currentId)); +} + +void LauncherAspect::updateLaunchers(const QList &launchers) +{ + if (m_launchers == launchers) + return; + m_launchers = launchers; + if (m_comboBox) + updateComboBox(); +} + +void LauncherAspect::setDefaultLauncher(const Launcher &launcher) +{ + if (m_defaultId == launcher.id) + return; + m_defaultId = launcher.id; + if (m_currentId.isEmpty()) + setCurrentLauncher(launcher); +} + +void LauncherAspect::setCurrentLauncher(const Launcher &launcher) +{ + if (m_comboBox) { + const int index = m_launchers.indexOf(launcher); + if (index < 0 || index >= m_comboBox->count()) + return; + m_comboBox->setCurrentIndex(index); + } else { + setCurrentLauncherId(launcher.id); + } +} + +void LauncherAspect::fromMap(const Store &map) +{ + setCurrentLauncherId(map.value(settingsKey(), m_defaultId).toString()); +} + +void LauncherAspect::toMap(Store &map) const +{ + if (m_currentId != m_defaultId) + saveToMap(map, m_currentId, QString(), settingsKey()); +} + +void LauncherAspect::addToLayout(Layout &builder) +{ + if (QTC_GUARD(m_comboBox.isNull())) + m_comboBox = new QComboBox; + + updateComboBox(); + connect(m_comboBox, &QComboBox::currentIndexChanged, + this, &LauncherAspect::updateCurrentLauncher); + + builder.addItems({Tr::tr("Launcher:"), m_comboBox.data()}); +} + +void LauncherAspect::setCurrentLauncherId(const QString &id) +{ + if (id == m_currentId) + return; + m_currentId = id; + emit changed(); +} + +void LauncherAspect::updateCurrentLauncher() +{ + const int index = m_comboBox->currentIndex(); + if (index < 0) + return; + QTC_ASSERT(index < m_launchers.size(), return); + m_comboBox->setToolTip(m_launchers[index].command.toUserOutput()); + setCurrentLauncherId(m_launchers[index].id); +} + +void LauncherAspect::updateComboBox() +{ + int currentIndex = -1; + int defaultIndex = -1; + m_comboBox->clear(); + for (const Launcher &launcher : std::as_const(m_launchers)) { + int index = m_comboBox->count(); + m_comboBox->addItem(launcher.displayName); + m_comboBox->setItemData(index, launcher.command.toUserOutput(), Qt::ToolTipRole); + if (launcher.id == m_currentId) + currentIndex = index; + if (launcher.id == m_defaultId) + defaultIndex = index; + } + if (currentIndex >= 0) + m_comboBox->setCurrentIndex(currentIndex); + else if (defaultIndex >= 0) + m_comboBox->setCurrentIndex(defaultIndex); + updateCurrentLauncher(); +} + /*! \class ProjectExplorer::X11ForwardingAspect \inmodule QtCreator diff --git a/src/plugins/projectexplorer/runconfigurationaspects.h b/src/plugins/projectexplorer/runconfigurationaspects.h index d891132ea7d..69b55c9974b 100644 --- a/src/plugins/projectexplorer/runconfigurationaspects.h +++ b/src/plugins/projectexplorer/runconfigurationaspects.h @@ -227,6 +227,36 @@ public: QString detectionSource; }; +class PROJECTEXPLORER_EXPORT LauncherAspect : public Utils::BaseAspect +{ + Q_OBJECT + +public: + LauncherAspect(Utils::AspectContainer *container = nullptr); + + Launcher currentLauncher() const; + void updateLaunchers(const QList &launchers); + void setDefaultLauncher(const Launcher &launcher); + void setCurrentLauncher(const Launcher &launcher); + void setSettingsDialogId(Utils::Id id) { m_settingsDialogId = id; } + + void fromMap(const Utils::Store &) override; + void toMap(Utils::Store &) const override; + void addToLayout(Layouting::Layout &parent) override; + + struct Data : Utils::BaseAspect::Data { Launcher launcher; }; + +private: + void setCurrentLauncherId(const QString &id); + void updateCurrentLauncher(); + void updateComboBox(); + QList m_launchers; + QPointer m_comboBox; + QString m_defaultId; + QString m_currentId; + Utils::Id m_settingsDialogId; +}; + class PROJECTEXPLORER_EXPORT MainScriptAspect : public Utils::FilePathAspect { Q_OBJECT diff --git a/src/plugins/projectexplorer/workspaceproject.cpp b/src/plugins/projectexplorer/workspaceproject.cpp index 6cbb858921b..ab90393c9e9 100644 --- a/src/plugins/projectexplorer/workspaceproject.cpp +++ b/src/plugins/projectexplorer/workspaceproject.cpp @@ -32,7 +32,7 @@ const QLatin1StringView WORKSPACE_PROJECT_RUNCONFIG_ID{"WorkspaceProject.RunConf const QLatin1StringView PROJECT_NAME_KEY{"project.name"}; const QLatin1StringView FILES_EXCLUDE_KEY{"files.exclude"}; const QLatin1StringView EXCLUDE_ACTION_ID{"ProjectExplorer.ExcludeFromWorkspace"}; - +const QLatin1StringView RESCAN_ACTION_ID{"ProjectExplorer.RescanWorkspace"}; using namespace Utils; using namespace Core; @@ -308,29 +308,61 @@ void setupWorkspaceProject(QObject *guard) ProjectManager::registerProjectType(FOLDER_MIMETYPE); ProjectManager::registerProjectType(WORKSPACE_MIMETYPE); + QAction *excludeAction = nullptr; + ActionBuilder(guard, Id::fromString(EXCLUDE_ACTION_ID)) + .setContext(Id::fromString(WORKSPACE_PROJECT_ID)) + .setText(Tr::tr("Exclude from Project")) + .addToContainer(Constants::M_FOLDERCONTEXT, Constants::G_FOLDER_OTHER) + .addToContainer(Constants::M_FILECONTEXT, Constants::G_FILE_OTHER) + .bindContextAction(&excludeAction) + .setCommandAttribute(Command::CA_Hide) + .addOnTriggered(guard, [] { + Node *node = ProjectTree::currentNode(); + QTC_ASSERT(node, return); + const auto project = qobject_cast(node->getProject()); + QTC_ASSERT(project, return); + project->excludeNode(node); + }); + + QAction *rescanAction = nullptr; + ActionBuilder(guard, Id::fromString(RESCAN_ACTION_ID)) + .setContext(Id::fromString(WORKSPACE_PROJECT_ID)) + .setText(Tr::tr("Rescan Workspace")) + .addToContainer(Constants::M_PROJECTCONTEXT, Constants::G_PROJECT_REBUILD) + .bindContextAction(&rescanAction) + .setCommandAttribute(Command::CA_Hide) + .addOnTriggered(guard, [] { + Node *node = ProjectTree::currentNode(); + QTC_ASSERT(node, return); + const auto project = qobject_cast(node->getProject()); + QTC_ASSERT(project, return); + if (auto target = project->activeTarget()) { + if (target->buildSystem()) + target->buildSystem()->triggerParsing(); + } + }); + QObject::connect( ProjectTree::instance(), &ProjectTree::aboutToShowContextMenu, ProjectExplorerPlugin::instance(), - [](Node *node) { - const bool enabled = node && node->isEnabled() - && qobject_cast(node->getProject()); - ActionManager::command(Id::fromString(EXCLUDE_ACTION_ID))->action()->setEnabled(enabled); + [excludeAction, rescanAction](Node *node) { + const bool visible = node && qobject_cast(node->getProject()); + excludeAction->setVisible(visible); + rescanAction->setVisible(visible); + if (visible) { + excludeAction->setEnabled(node->isEnabled()); + bool enableRescan = false; + if (Project *project = node->getProject()) { + if (Target *target = project->activeTarget()) { + if (BuildSystem *buildSystem = target->buildSystem()) + enableRescan = !buildSystem->isParsing(); + } + } + rescanAction->setEnabled(enableRescan); + } }); - ActionBuilder excludeAction(guard, Id::fromString(EXCLUDE_ACTION_ID)); - excludeAction.setContext(Id::fromString(WORKSPACE_PROJECT_ID)); - excludeAction.setText(Tr::tr("Exclude from Project")); - excludeAction.addToContainer(Constants::M_FOLDERCONTEXT, Constants::G_FOLDER_OTHER); - excludeAction.addToContainer(Constants::M_FILECONTEXT, Constants::G_FILE_OTHER); - excludeAction.addOnTriggered([] { - Node *node = ProjectTree::currentNode(); - QTC_ASSERT(node, return); - const auto project = qobject_cast(node->getProject()); - QTC_ASSERT(project, return); - project->excludeNode(node); - }); - static WorkspaceProjectRunConfigurationFactory theRunConfigurationFactory; static WorkspaceProjectRunWorkerFactory theRunWorkerFactory; } diff --git a/src/plugins/qbsprojectmanager/qbsbuildstep.cpp b/src/plugins/qbsprojectmanager/qbsbuildstep.cpp index 9d0a9f642cf..c079f007b16 100644 --- a/src/plugins/qbsprojectmanager/qbsbuildstep.cpp +++ b/src/plugins/qbsprojectmanager/qbsbuildstep.cpp @@ -610,7 +610,7 @@ void QbsBuildStepConfigWidget::changeUseDefaultInstallDir(bool useDefault) if (useDefault) config.remove(Constants::QBS_INSTALL_ROOT_KEY); else - config.insert(Constants::QBS_INSTALL_ROOT_KEY, installDirChooser->rawFilePath().toString()); + config.insert(Constants::QBS_INSTALL_ROOT_KEY, installDirChooser->unexpandedFilePath().toString()); m_qbsStep->setQbsConfiguration(config); } @@ -620,7 +620,7 @@ void QbsBuildStepConfigWidget::changeInstallDir() return; const GuardLocker locker(m_ignoreChanges); Store config = m_qbsStep->qbsConfiguration(QbsBuildStep::PreserveVariables); - config.insert(Constants::QBS_INSTALL_ROOT_KEY, installDirChooser->rawFilePath().toString()); + config.insert(Constants::QBS_INSTALL_ROOT_KEY, installDirChooser->unexpandedFilePath().toString()); m_qbsStep->setQbsConfiguration(config); } diff --git a/src/plugins/qmldesigner/components/richtexteditor/richtexteditor.cpp b/src/plugins/qmldesigner/components/richtexteditor/richtexteditor.cpp index 8a9ed00c400..940b121b9ed 100644 --- a/src/plugins/qmldesigner/components/richtexteditor/richtexteditor.cpp +++ b/src/plugins/qmldesigner/components/richtexteditor/richtexteditor.cpp @@ -532,7 +532,7 @@ void RichTextEditor::setupFontActions() w->setCurrentIndex(w->findText(m_textEdit->currentCharFormat().font().family())); connect(w, &QComboBox::textActivated, [this](const QString &f) { QTextCharFormat fmt; - fmt.setFontFamily(f); + fmt.setFontFamilies({f}); mergeFormatOnWordOrSelection(fmt); }); }); diff --git a/src/plugins/qmljseditor/qmljseditingsettingspage.cpp b/src/plugins/qmljseditor/qmljseditingsettingspage.cpp index 6c9286659f9..4d492781c2a 100644 --- a/src/plugins/qmljseditor/qmljseditingsettingspage.cpp +++ b/src/plugins/qmljseditor/qmljseditingsettingspage.cpp @@ -35,6 +35,7 @@ const char QML_CONTEXTPANEPIN_KEY[] = "QmlJSEditor.ContextPanePinned"; const char FOLD_AUX_DATA[] = "QmlJSEditor.FoldAuxData"; const char USE_QMLLS[] = "QmlJSEditor.UseQmlls"; const char USE_LATEST_QMLLS[] = "QmlJSEditor.UseLatestQmlls"; +const char IGNORE_MINIMUM_QMLLS_VERSION[] = "QmlJSEditor.IgnoreMinimumQmllsVersion"; const char DISABLE_BUILTIN_CODEMODEL[] = "QmlJSEditor.DisableBuiltinCodemodel"; const char GENERATE_QMLLS_INI_FILES[] = "QmlJSEditor.GenerateQmllsIniFiles"; const char UIQML_OPEN_MODE[] = "QmlJSEditor.openUiQmlMode"; @@ -107,8 +108,9 @@ void QmlJsEditingSettings::fromSettings(QtcSettings *settings) m_uiQmlOpenMode = settings->value(UIQML_OPEN_MODE, "").toString(); m_useQmlls = settings->value(USE_QMLLS, QVariant(true)).toBool(); m_useLatestQmlls = settings->value(USE_LATEST_QMLLS, QVariant(false)).toBool(); - m_disableBuiltinCodemodel - = settings->value(DISABLE_BUILTIN_CODEMODEL, QVariant(false)).toBool(); + m_ignoreMinimumQmllsVersion + = settings->value(IGNORE_MINIMUM_QMLLS_VERSION, QVariant(false)).toBool(); + m_disableBuiltinCodemodel = settings->value(DISABLE_BUILTIN_CODEMODEL, QVariant(false)).toBool(); m_generateQmllsIniFiles = settings->value(GENERATE_QMLLS_INI_FILES, QVariant(false)).toBool(); m_formatCommand = settings->value(FORMAT_COMMAND, {}).toString(); @@ -138,6 +140,7 @@ void QmlJsEditingSettings::toSettings(QtcSettings *settings) const settings->setValue(UIQML_OPEN_MODE, m_uiQmlOpenMode); settings->setValue(USE_QMLLS, m_useQmlls); settings->setValue(USE_LATEST_QMLLS, m_useLatestQmlls); + settings->setValue(IGNORE_MINIMUM_QMLLS_VERSION, m_ignoreMinimumQmllsVersion); settings->setValue(DISABLE_BUILTIN_CODEMODEL, m_disableBuiltinCodemodel); settings->setValue(GENERATE_QMLLS_INI_FILES, m_generateQmllsIniFiles); settings->setValueWithDefault(FORMAT_COMMAND, m_formatCommand, {}); @@ -329,6 +332,16 @@ void QmlJsEditingSettings::setUseLatestQmlls(bool newUseLatestQmlls) m_useLatestQmlls = newUseLatestQmlls; } +bool QmlJsEditingSettings::ignoreMinimumQmllsVersion() const +{ + return m_ignoreMinimumQmllsVersion; +} + +void QmlJsEditingSettings::setIgnoreMinimumQmllsVersion(bool newIgnoreMinimumQmllsVersion) +{ + m_ignoreMinimumQmllsVersion = newIgnoreMinimumQmllsVersion; +} + bool QmlJsEditingSettings::useQmlls() const { return m_useQmlls; @@ -434,6 +447,13 @@ public: useQmlls = new QCheckBox(Tr::tr("Enable QML Language Server")); useQmlls->setChecked(s.useQmlls()); + + ignoreMinimumQmllsVersion = new QCheckBox( + Tr::tr("Allow versions below Qt %1") + .arg(QmllsSettingsManager::mininumQmllsVersion.toString())); + ignoreMinimumQmllsVersion->setChecked(s.ignoreMinimumQmllsVersion()); + ignoreMinimumQmllsVersion->setEnabled(s.useQmlls()); + disableBuiltInCodemodel = new QCheckBox( Tr::tr("Use QML Language Server advanced features (renaming, find usages and co.) " "(EXPERIMENTAL!)")); @@ -442,6 +462,7 @@ public: useLatestQmlls = new QCheckBox(Tr::tr("Use QML Language Server from latest Qt version")); useLatestQmlls->setChecked(s.useLatestQmlls()); useLatestQmlls->setEnabled(s.useQmlls()); + generateQmllsIniFiles = new QCheckBox( Tr::tr("Generate QML Language Server .qmlls.ini configurations for new projects.")); generateQmllsIniFiles->setChecked(s.generateQmllsIniFiles()); @@ -450,6 +471,7 @@ public: useLatestQmlls->setEnabled(checked != Qt::Unchecked); disableBuiltInCodemodel->setEnabled(checked != Qt::Unchecked); generateQmllsIniFiles->setEnabled(checked != Qt::Unchecked); + ignoreMinimumQmllsVersion->setEnabled(checked != Qt::Unchecked); }); useCustomAnalyzer = new QCheckBox(Tr::tr("Use customized static analyzer")); @@ -502,7 +524,7 @@ public: }, Group{ title(Tr::tr("QML Language Server")), - Column{useQmlls, disableBuiltInCodemodel , useLatestQmlls, generateQmllsIniFiles}, + Column{useQmlls, ignoreMinimumQmllsVersion, disableBuiltInCodemodel, useLatestQmlls, generateQmllsIniFiles}, }, Group { title(Tr::tr("Static Analyzer")), @@ -548,6 +570,7 @@ public: s.setUseQmlls(useQmlls->isChecked()); s.setDisableBuiltinCodemodel(disableBuiltInCodemodel->isChecked()); s.setUseLatestQmlls(useLatestQmlls->isChecked()); + s.setIgnoreMinimumQmllsVersion(ignoreMinimumQmllsVersion->isChecked()); s.setGenerateQmllsIniFiles(generateQmllsIniFiles->isChecked()); s.setUseCustomAnalyzer(useCustomAnalyzer->isChecked()); QSet disabled; @@ -606,6 +629,7 @@ private: QCheckBox *foldAuxData; QCheckBox *useQmlls; QCheckBox *useLatestQmlls; + QCheckBox *ignoreMinimumQmllsVersion; QCheckBox *disableBuiltInCodemodel; QCheckBox *generateQmllsIniFiles; QComboBox *uiQmlOpenComboBox; diff --git a/src/plugins/qmljseditor/qmljseditingsettingspage.h b/src/plugins/qmljseditor/qmljseditingsettingspage.h index f7eee42cdb6..99dd335f11a 100644 --- a/src/plugins/qmljseditor/qmljseditingsettingspage.h +++ b/src/plugins/qmljseditor/qmljseditingsettingspage.h @@ -68,6 +68,9 @@ public: bool useLatestQmlls() const; void setUseLatestQmlls(bool newUseLatestQmlls); + bool ignoreMinimumQmllsVersion() const; + void setIgnoreMinimumQmllsVersion(bool newIgnoreMinimumQmllsVersion); + bool disableBuiltinCodemodel() const; void setDisableBuiltinCodemodel(bool newDisableBuiltinCodemodel); @@ -89,6 +92,7 @@ private: bool m_useCustomAnalyzer = false; bool m_useQmlls = true; bool m_useLatestQmlls = false; + bool m_ignoreMinimumQmllsVersion = false; bool m_disableBuiltinCodemodel = false; bool m_generateQmllsIniFiles = false; QString m_uiQmlOpenMode; diff --git a/src/plugins/qmljseditor/qmljseditordocument.cpp b/src/plugins/qmljseditor/qmljseditordocument.cpp index 582516da1b5..445abaa4321 100644 --- a/src/plugins/qmljseditor/qmljseditordocument.cpp +++ b/src/plugins/qmljseditor/qmljseditordocument.cpp @@ -744,6 +744,12 @@ static Utils::FilePath qmllsForFile(const Utils::FilePath &file, if (settingsManager->useLatestQmlls()) return settingsManager->latestQmlls(); QmlJS::ModelManagerInterface::ProjectInfo pInfo = modelManager->projectInfoForPath(file); + + if (!settingsManager->ignoreMinimumQmllsVersion() + && QVersionNumber::fromString(pInfo.qtVersionString) + < QmllsSettingsManager::mininumQmllsVersion) { + return {}; + } return pInfo.qmllsPath; } diff --git a/src/plugins/qmljseditor/qmllssettings.cpp b/src/plugins/qmljseditor/qmllssettings.cpp index 7fdcbc109e6..170f3122709 100644 --- a/src/plugins/qmljseditor/qmllssettings.cpp +++ b/src/plugins/qmljseditor/qmllssettings.cpp @@ -33,9 +33,13 @@ static FilePath evaluateLatestQmlls() QVersionNumber latestVersion; FilePath latestQmakeFilePath; int latestUniqueId = std::numeric_limits::min(); + const bool ignoreMinimumQmllsVersion + = QmllsSettingsManager::instance()->ignoreMinimumQmllsVersion(); for (QtVersion *v : versions) { // check if we find qmlls QVersionNumber vNow = v->qtVersion(); + if (!ignoreMinimumQmllsVersion && vNow < QmllsSettingsManager::mininumQmllsVersion) + continue; FilePath qmllsNow = QmlJS::ModelManagerInterface::qmllsForBinPath(v->hostBinPath(), vNow); if (!qmllsNow.isExecutableFile()) continue; @@ -113,6 +117,11 @@ bool QmllsSettingsManager::useLatestQmlls() const return m_useLatestQmlls; } +bool QmllsSettingsManager::ignoreMinimumQmllsVersion() const +{ + return m_ignoreMinimumQmllsVersion; +} + bool QmllsSettingsManager::useQmlls() const { return m_useQmlls; diff --git a/src/plugins/qmljseditor/qmllssettings.h b/src/plugins/qmljseditor/qmllssettings.h index b4cc3ac176b..c1a82b986b8 100644 --- a/src/plugins/qmljseditor/qmllssettings.h +++ b/src/plugins/qmljseditor/qmllssettings.h @@ -6,8 +6,10 @@ #include "qmljseditor_global.h" #include + #include #include +#include namespace QmlJSEditor { @@ -16,6 +18,8 @@ class QMLJSEDITOR_EXPORT QmllsSettingsManager : public QObject Q_OBJECT public: + static const inline QVersionNumber mininumQmllsVersion = QVersionNumber(6, 8); + static QmllsSettingsManager *instance(); Utils::FilePath latestQmlls(); @@ -23,6 +27,7 @@ public: bool useQmlls() const; bool useLatestQmlls() const; + bool ignoreMinimumQmllsVersion() const; public slots: void checkForChanges(); @@ -33,6 +38,7 @@ private: QMutex m_mutex; bool m_useQmlls = true; bool m_useLatestQmlls = false; + bool m_ignoreMinimumQmllsVersion = false; bool m_disableBuiltinCodemodel = false; bool m_generateQmllsIniFiles = false; Utils::FilePath m_latestQmlls; diff --git a/src/plugins/qtsupport/qtoptionspage.cpp b/src/plugins/qtsupport/qtoptionspage.cpp index 7b08db2351a..3be1bc2570b 100644 --- a/src/plugins/qtsupport/qtoptionspage.cpp +++ b/src/plugins/qtsupport/qtoptionspage.cpp @@ -1036,7 +1036,7 @@ void QtSettingsPageWidget::linkWithQt() dialog.exec(); if (dialog.result() == QDialog::Accepted) { const std::optional settingsDir = settingsDirForQtDir(pathInput->baseDirectory(), - pathInput->rawFilePath()); + pathInput->unexpandedFilePath()); if (QTC_GUARD(settingsDir)) { const QString settingsFilePath = settingsFile(ICore::resourcePath().toString()); QSettings settings(settingsFilePath, QSettings::IniFormat); diff --git a/src/plugins/rustls/CMakeLists.txt b/src/plugins/rustls/CMakeLists.txt deleted file mode 100644 index 17184ddf139..00000000000 --- a/src/plugins/rustls/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -add_qtc_lua_plugin(rustls - SOURCES rustls/rustls.lua - rustls/init.lua -) diff --git a/src/plugins/rustls/rustls.qbs b/src/plugins/rustls/rustls.qbs deleted file mode 100644 index f629705f098..00000000000 --- a/src/plugins/rustls/rustls.qbs +++ /dev/null @@ -1,8 +0,0 @@ -QtcLuaPlugin { - name: "rustls" - - luafiles: [ - "init.lua", - "rustls.lua", - ] -} diff --git a/src/plugins/tellajoke/CMakeLists.txt b/src/plugins/tellajoke/CMakeLists.txt deleted file mode 100644 index c9dfcf23d20..00000000000 --- a/src/plugins/tellajoke/CMakeLists.txt +++ /dev/null @@ -1 +0,0 @@ -add_qtc_lua_plugin(tellajoke SOURCES tellajoke/tellajoke.lua) diff --git a/src/plugins/tellajoke/tellajoke.qbs b/src/plugins/tellajoke/tellajoke.qbs deleted file mode 100644 index d2efc1a64e8..00000000000 --- a/src/plugins/tellajoke/tellajoke.qbs +++ /dev/null @@ -1,5 +0,0 @@ -QtcLuaPlugin { - name: "tellajoke" - - luafiles: "tellajoke.lua" -} diff --git a/src/plugins/texteditor/bookmarkmanager.cpp b/src/plugins/texteditor/bookmarkmanager.cpp index a61cc587363..625eca0c251 100644 --- a/src/plugins/texteditor/bookmarkmanager.cpp +++ b/src/plugins/texteditor/bookmarkmanager.cpp @@ -218,7 +218,6 @@ BookmarkView::BookmarkView() setDragEnabled(true); setDragDropMode(QAbstractItemView::DragDrop); - connect(this, &QAbstractItemView::doubleClicked, this, &BookmarkView::gotoBookmark); connect(this, &QAbstractItemView::activated, this, &BookmarkView::gotoBookmark); } diff --git a/src/plugins/texteditor/fontsettings.cpp b/src/plugins/texteditor/fontsettings.cpp index 44b179d01c8..3cb58fd1282 100644 --- a/src/plugins/texteditor/fontsettings.cpp +++ b/src/plugins/texteditor/fontsettings.cpp @@ -156,7 +156,7 @@ QTextCharFormat FontSettings::toTextCharFormat(TextStyle category) const QTextCharFormat tf; if (category == C_TEXT) { - tf.setFontFamily(m_family); + tf.setFontFamilies({m_family}); tf.setFontPointSize(m_fontSize * m_fontZoom / 100.); tf.setFontStyleStrategy(m_antialias ? QFont::PreferAntialias : QFont::NoAntialias); } diff --git a/src/plugins/valgrind/valgrindsettings.cpp b/src/plugins/valgrind/valgrindsettings.cpp index 47f45973747..0a92f391d3b 100644 --- a/src/plugins/valgrind/valgrindsettings.cpp +++ b/src/plugins/valgrind/valgrindsettings.cpp @@ -392,19 +392,8 @@ ValgrindSettings::ValgrindSettings(bool global) // clang-format on }); - if (global) { + if (global) readSettings(); - } else { - // FIXME: Is this needed? - connect(this, &AspectContainer::fromMapFinished, [this] { - // FIXME: Update project page e.g. on "Restore Global", aspects - // there are 'autoapply', and Aspect::cancel() is normally part of - // the 'manual apply' machinery. - setAutoApply(false); - cancel(); - setAutoApply(true); - }); - } } ValgrindSettings &globalSettings() diff --git a/src/shared/qbs b/src/shared/qbs index f67d43fc24b..2e54309c02a 160000 --- a/src/shared/qbs +++ b/src/shared/qbs @@ -1 +1 @@ -Subproject commit f67d43fc24bec11a6b599d46304ea06e15218acd +Subproject commit 2e54309c02a56c602909ee3f4fef6c654a616c85 diff --git a/src/tools/icons/qtcreatoricons.svg b/src/tools/icons/qtcreatoricons.svg index 7aa9fe1bed7..01ec12e64ba 100644 --- a/src/tools/icons/qtcreatoricons.svg +++ b/src/tools/icons/qtcreatoricons.svg @@ -1975,6 +1975,48 @@ id="path4127-25-8" /> + + + + + + + + +