diff --git a/.github/workflows/build_cmake.yml b/.github/workflows/build_cmake.yml index 45d9c8144f1..d57ece196a4 100644 --- a/.github/workflows/build_cmake.yml +++ b/.github/workflows/build_cmake.yml @@ -391,6 +391,7 @@ jobs: COMMAND python -u scripts/build.py + --build-type Release --src . --build build --qt-path "${{ steps.qt.outputs.qt_dir }}" diff --git a/CMakeLists.txt b/CMakeLists.txt index 440418e2b87..9a34f1c9183 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,7 +4,7 @@ cmake_minimum_required(VERSION 3.10) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") include(FeatureSummary) -include(QtCreatorIDEBranding) +include(QtCreatorIDEBranding RESULT_VARIABLE IDE_BRANDING_FILE) include(QtCreatorTranslations) include(QtCreatorDocumentation) include(QtCreatorAPI) diff --git a/cmake/FindQt5.cmake b/cmake/FindQt5.cmake index f18745e5983..2ace18f8eb1 100644 --- a/cmake/FindQt5.cmake +++ b/cmake/FindQt5.cmake @@ -69,7 +69,7 @@ set(Qt5_VERSION ${Qt6_VERSION}) foreach(tool qmake lrelease moc rcc qhelpgenerator) if (TARGET Qt6::${tool} AND NOT TARGET Qt5::${tool}) add_executable(Qt5::${tool} IMPORTED GLOBAL) - get_target_property(imported_location Qt6::${tool} IMPORTED_LOCATION_RELEASE) + get_target_property(imported_location Qt6::${tool} IMPORTED_LOCATION) set_target_properties(Qt5::${tool} PROPERTIES IMPORTED_LOCATION "${imported_location}") endif() endforeach() diff --git a/cmake/Findyaml-cpp.cmake b/cmake/Findyaml-cpp.cmake index d8e92f070d4..2c5b2a60d25 100644 --- a/cmake/Findyaml-cpp.cmake +++ b/cmake/Findyaml-cpp.cmake @@ -114,5 +114,8 @@ else() ${YAML_SOURCE_DIR}/src/tag.h ${YAML_SOURCE_DIR}/src/token.h ) + if(MSVC) + target_compile_options(yaml-cpp PUBLIC /wd4251 /wd4275) + endif() unset(YAML_SOURCE_DIR) endif() diff --git a/cmake/QtCreatorAPI.cmake b/cmake/QtCreatorAPI.cmake index 0221248faed..816c1a7e4ae 100644 --- a/cmake/QtCreatorAPI.cmake +++ b/cmake/QtCreatorAPI.cmake @@ -133,7 +133,7 @@ function(add_qtc_library name) endif() add_library(${name} ${library_type} ${_arg_SOURCES}) - add_library(${IDE_CASED_ID}::${name} ALIAS ${name}) + add_library(QtCreator::${name} ALIAS ${name}) set_public_headers(${name} "${_arg_SOURCES}") # TODO remove, see above @@ -339,9 +339,9 @@ function(add_qtc_plugin target_name) set(_arg_DEPENDENCY_STRING "\"Dependencies\" : [\n") foreach(i IN LISTS _DEP_PLUGINS) - if (i MATCHES "^${IDE_CASED_ID}::") + if (i MATCHES "^QtCreator::") set(_v ${IDE_VERSION}) - string(REPLACE "${IDE_CASED_ID}::" "" i ${i}) + string(REPLACE "QtCreator::" "" i ${i}) else() get_property(_v TARGET "${i}" PROPERTY _arg_VERSION) endif() @@ -353,9 +353,9 @@ function(add_qtc_plugin target_name) _arg_DEPENDENCY_STRING "${_arg_DEPENDENCY_STRING}" ) foreach(i IN LISTS ${_arg_RECOMMENDS}) - if (i MATCHES "^${IDE_CASED_ID}::") + if (i MATCHES "^QtCreator::") set(_v ${IDE_VERSION}) - string(REPLACE "${IDE_CASED_ID}::" "" i ${i}) + string(REPLACE "QtCreator::" "" i ${i}) else() get_property(_v TARGET "${i}" PROPERTY _arg_VERSION) endif() @@ -393,7 +393,7 @@ function(add_qtc_plugin target_name) endif() add_library(${target_name} SHARED ${_arg_SOURCES}) - add_library(${IDE_CASED_ID}::${target_name} ALIAS ${target_name}) + add_library(QtCreator::${target_name} ALIAS ${target_name}) set_public_headers(${target_name} "${_arg_SOURCES}") ### Generate EXPORT_SYMBOL @@ -598,7 +598,10 @@ function(add_qtc_executable name) if (_prop_OUTPUT_NAME) set(_BUNDLE_NAME "${_prop_OUTPUT_NAME}") endif() - set(_EXECUTABLE_PATH "${_DESTINATION}/${_BUNDLE_NAME}.app/Contents/MacOS") + set(_BUNDLE_CONTENTS_PATH "${_DESTINATION}/${_BUNDLE_NAME}.app/Contents") + set(_EXECUTABLE_PATH "${_BUNDLE_CONTENTS_PATH}/MacOS") + set(_EXECUTABLE_FILE_PATH "${_EXECUTABLE_PATH}/${_BUNDLE_NAME}") + set(_BUNDLE_INFO_PLIST "${_BUNDLE_CONTENTS_PATH}/Info.plist") endif() endif() @@ -647,11 +650,70 @@ function(add_qtc_executable name) set(COMPONENT_OPTION "COMPONENT" "${_arg_COMPONENT}") endif() - install(TARGETS ${name} - DESTINATION "${_DESTINATION}" - ${COMPONENT_OPTION} - OPTIONAL - ) + # work around the issue that CMake simply copies the bundle directory + # when installing app bundles, which copies things that it should not + # like static libraries, executables with SKIP_INSTALL, clang resources + # and dSYM directories + if (APPLE AND _EXECUTABLE_FILE_PATH AND _BUNDLE_INFO_PLIST) + install( + PROGRAMS "${_output_binary_dir}/${_EXECUTABLE_FILE_PATH}" + DESTINATION "${_EXECUTABLE_PATH}" + ${COMPONENT_OPTION} + OPTIONAL + ) + install( + FILES "${_output_binary_dir}/${_BUNDLE_INFO_PLIST}" + DESTINATION "${_BUNDLE_CONTENTS_PATH}" + ${COMPONENT_OPTION} + OPTIONAL + ) + # Remove build-rpaths. That is BUILD_RPATH and the ones added because we + # don't use SKIP_BUILD_RPATH + set(_rpaths_to_remove ${build_rpath}) + get_target_property(_linked_libs ${name} LINK_LIBRARIES) + foreach(_lib ${_linked_libs}) + get_target_property(_target_type ${_lib} TYPE) + if (_target_type STREQUAL "SHARED_LIBRARY") + get_target_property(_location ${_lib} LIBRARY_OUTPUT_DIRECTORY) + if (_location) + get_filename_component(_abs_location ${_location} ABSOLUTE) + list(APPEND _rpaths_to_remove "${_abs_location}") + else() + get_target_property(_location ${_lib} LOCATION) + get_target_property(_is_framework ${_lib} FRAMEWORK) + if (_is_framework) + set(_location ${_location}/../..) + endif() + get_filename_component(_abs_location ${_location} ABSOLUTE) + list(APPEND _rpaths_to_remove "${_abs_location}") + endif() + endif() + endforeach() + list(REMOVE_DUPLICATES _rpaths_to_remove) + set(_code) + foreach(_rpath ${_rpaths_to_remove}) + set(_code "${_code} + execute_process(COMMAND \"${CMAKE_INSTALL_NAME_TOOL}\" + -delete_rpath \"${_rpath}\" + \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${_EXECUTABLE_FILE_PATH}\")" + ) + endforeach() + foreach(_rpath ${install_rpath}) + set(_code "${_code} + execute_process(COMMAND \"${CMAKE_INSTALL_NAME_TOOL}\" + -add_rpath \"${_rpath}\" + \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${_EXECUTABLE_FILE_PATH}\")" + ) + endforeach() + install(CODE "${_code}") + else() + install(TARGETS ${name} + DESTINATION "${_DESTINATION}" + ${COMPONENT_OPTION} + OPTIONAL + ) + endif() + update_cached_list(__QTC_INSTALLED_EXECUTABLES "${_DESTINATION}/${name}${CMAKE_EXECUTABLE_SUFFIX}") diff --git a/dist/changes-4.13.3.md b/dist/changes-4.13.3.md new file mode 100644 index 00000000000..5f8c0ea8661 --- /dev/null +++ b/dist/changes-4.13.3.md @@ -0,0 +1,77 @@ +Qt Creator 4.13.3 +================= + +Qt Creator version 4.13.3 contains bug fixes. + +The most important changes are listed in this document. For a complete list of +changes, see the Git log for the Qt Creator sources that you can check out from +the public Git repository. For example: + + git clone git://code.qt.io/qt-creator/qt-creator.git + git log --cherry-pick --pretty=oneline origin/v4.13.2..v4.13.3 + +General +------- + +* Updated prebuilt binaries to Qt 5.15.2 which fixes drag & drop on macOS + +Editing +------- + +### QML + +* Fixed reformatting of required properties (QTCREATORBUG-24376) +* Fixed importing without specific version for Qt 6 (QTCREATORBUG-24533) + +Projects +-------- + +* Fixed auto-scrolling of compile output window (QTCREATORBUG-24728) +* Fixed GitHub Actions for Qt Creator plugin wizard (QTCREATORBUG-24412) +* Fixed crash with `Manage Sessions` (QTCREATORBUG-24797) + +Qt Quick Designer +----------------- + +* Fixed crash when opening malformed `.ui.qml` file (QTCREATORBUG-24587) + +Debugging +--------- + +### CDB + +* Fixed pretty printing of `std::vector` and `std::string` in release mode + +Analyzer +-------- + +### QML Profiler + +* Fixed crash with `Analyze Current Range` (QTCREATORBUG-24730) + +Platforms +--------- + +### Android + +* Fixed modified state of manifest editor when changing app icons + (QTCREATORBUG-24700) + +Credits for these changes go to: +-------------------------------- +Alexandru Croitor +Christian Kandeler +Christian Stenger +David Schulz +Dominik Holland +Eike Ziller +Fawzi Mohamed +Friedemann Kleint +Ivan Komissarov +Johanna Vanhatapio +Leena Miettinen +Lukasz Ornatek +Robert Löhning +Tim Jenssen +Ville Voutilainen +Xiaofeng Wang diff --git a/dist/changes-4.14.0.md b/dist/changes-4.14.0.md index 4da0dab84ae..d37f2e23db8 100644 --- a/dist/changes-4.14.0.md +++ b/dist/changes-4.14.0.md @@ -52,6 +52,8 @@ Editing * Fixed that `Complete switch statement` indents unrelated code (QTCREATORBUG-12445) * Fixed `Complete switch statement` with templates (QTCREATORBUG-24752) * Fixed `Complete switch statement` for enum classes (QTCREATORBUG-20475) +* Fixed creating and moving template member function definitions (QTCREATORBUG-24801, + QTCREATORBUG-24848) * Fixed that `Apply function signature change` removed return values from `std::function` arguments (QTCREATORBUG-13698) * Fixed handling of multiple inheritance in `Insert Virtual Functions` (QTCREATORBUG-12223) @@ -81,6 +83,8 @@ Projects * Renamed `CurrentProject:*` variables to `CurrentDocument:Project:*` (QTCREATORBUG-12724, QTCREATORBUG-24606) +* Added `ActiveProject:*` variables (QTCREATORBUG-24878) +* Changed `Qt Creator Plugin` wizard to CMake build system (QTCREATORBUG-24073) * Fixed issue when environment changes after appending or prepending path (QTCREATORBUG-24105) * Fixed `Embedding of the UI Class` option for widget applications (QTCREATORBUG-24422) * Fixed shell used for console applications (QTCREATORBUG-24659) @@ -107,11 +111,16 @@ Debugging --------- * Fixed disabling and enabling breakpoints (QTCREATORBUG-24669) +* Fixed setting source mappings with variables (QTCREATORBUG-24816) ### GDB * Fixed loading of symbol files with `Load Core File` (QTCREATORBUG-24541) +### CDB + +* Fixed debugging when `PYTHONPATH` is set (QTCREATORBUG-24859) + Analyzer -------- @@ -156,8 +165,13 @@ Platforms * Added missing Android variables to completion in `.pro` and `.pri` files * Fixed passing command line arguments to application (QTCREATORBUG-23712) +### MCU + +* Improved creation of kits (QTCREATORBUG-24354) + Credits for these changes go to: -------------------------------- +Aleksei German Alessandro Portale Alexander Mishin Alexis Jeandet @@ -166,6 +180,7 @@ André Pönitz Antonio Di Monaco Asit Dhal Assam Boudjelthia +Christiaan Janssen Christian Kandeler Christian Stenger Cristian Adam @@ -176,14 +191,19 @@ Fabio Falsini Fawzi Mohamed Federico Guerinoni Henning Gruendl +Jaroslaw Kobus Jeremy Ephron +Jochen Seemann +Johanna Vanhatapio Kai Köhne Knud Dollereder Lars Knoll Leander Schulten Leena Miettinen +Lukas Holecek Lukasz Ornatek Mahmoud Badri +Marco Bubke Martin Kampas Michael Weghorn Miikka Heikkinen @@ -194,6 +214,7 @@ Robert Löhning Tasuku Suzuki Thiago Macieira Thomas Hartmann +Tim Jenssen Tobias Hunger Vikas Pachdha Volodymyr Zibarov diff --git a/doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-components.qdoc b/doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-components.qdoc index 8b3f8cb91df..5a28bdc5970 100644 --- a/doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-components.qdoc +++ b/doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-components.qdoc @@ -51,7 +51,7 @@ You can use the model component to load static mesh data from storage or one of the built-in primitive types: cube, cone, - cylinder, rectangle, or sphere. You can attach materials to + cylinder, plane (rectangle), or sphere. You can attach materials to meshes and sub-meshes. \li \l {Using Materials and Shaders} @@ -85,9 +85,9 @@ scene and set their properties. \li \l {Using Scene Camera} - To project a 3D scene to a 2D viewport, it is necessary to view - the scene from a camera. You can select the camera type and set - its properties. + To project a 3D scene to a 2D viewport, such as + \uicontrol {Form Editor}, it is necessary to view the scene from a + camera. You can select the camera type and set its properties. \li \l {Setting Scene Environment} You can use the SceneEnvironment type to specify how the scene is diff --git a/scripts/build.py b/scripts/build.py index 1fcc7fb66df..53609033716 100755 --- a/scripts/build.py +++ b/scripts/build.py @@ -54,7 +54,8 @@ def get_arguments(): parser.add_argument('--build', help='path that should be used for building', required=True) parser.add_argument('--qt-path', help='Path to Qt', required=True) - parser.add_argument('--debug', help='Enable debug builds', action='store_true', default=False) + parser.add_argument('--build-type', help='Build type to pass to CMake (defaults to RelWithDebInfo)', + default='RelWithDebInfo') # clang codemodel parser.add_argument('--llvm-path', help='Path to LLVM installation for Clang code model', @@ -113,13 +114,12 @@ def build_qtcreator(args, paths): if paths.elfutils: prefix_paths += [paths.elfutils] prefix_paths = [common.to_posix_path(fp) for fp in prefix_paths] - build_type = 'Debug' if args.debug else 'Release' with_docs_str = 'OFF' if args.no_docs else 'ON' build_date_option = 'OFF' if args.no_build_date else 'ON' test_option = 'ON' if args.with_tests else 'OFF' cmake_args = ['cmake', '-DCMAKE_PREFIX_PATH=' + ';'.join(prefix_paths), - '-DCMAKE_BUILD_TYPE=' + build_type, + '-DCMAKE_BUILD_TYPE=' + args.build_type, '-DSHOW_BUILD_DATE=' + build_date_option, '-DWITH_DOCS=' + with_docs_str, '-DBUILD_DEVELOPER_DOCS=' + with_docs_str, diff --git a/scripts/build_plugin.py b/scripts/build_plugin.py index 43b8056c0f6..a8d40424a9f 100755 --- a/scripts/build_plugin.py +++ b/scripts/build_plugin.py @@ -57,7 +57,8 @@ def get_arguments(): action='store_true', default=False) parser.add_argument('--deploy', help='Installs the "Dependencies" component of the plugin.', action='store_true', default=False) - parser.add_argument('--debug', help='Enable debug builds', action='store_true', default=False) + parser.add_argument('--build-type', help='Build type to pass to CMake (defaults to RelWithDebInfo)', + default='RelWithDebInfo') return parser.parse_args() def build(args, paths): @@ -67,10 +68,9 @@ def build(args, paths): os.makedirs(paths.result) prefix_paths = [os.path.abspath(fp) for fp in args.prefix_paths] + [paths.qt_creator, paths.qt] prefix_paths = [common.to_posix_path(fp) for fp in prefix_paths] - build_type = 'Debug' if args.debug else 'Release' cmake_args = ['cmake', '-DCMAKE_PREFIX_PATH=' + ';'.join(prefix_paths), - '-DCMAKE_BUILD_TYPE=' + build_type, + '-DCMAKE_BUILD_TYPE=' + args.build_type, '-DCMAKE_INSTALL_PREFIX=' + common.to_posix_path(paths.install), '-G', 'Ninja'] diff --git a/scripts/shiboken2tasks.py b/scripts/shiboken2tasks.py index 024f53cd15c..9465ad7f786 100755 --- a/scripts/shiboken2tasks.py +++ b/scripts/shiboken2tasks.py @@ -36,7 +36,8 @@ import re if __name__ == '__main__': # qt.shiboken: () ::[:] text - pattern = re.compile(r'^qt\.shiboken: \(([^)]+)\) ([^:]+):(\d+):(?:\d+:)? (.*)$') + # file might be c:\ on Windows + pattern = re.compile(r'^qt\.shiboken: \(([^)]+)\) (..[^:]+):(\d+):(?:\d+:)? (.*)$') while True: line = sys.stdin.readline() if not line: diff --git a/share/qtcreator/CMakeLists.txt b/share/qtcreator/CMakeLists.txt index 622761f4d8a..667ef9259c1 100644 --- a/share/qtcreator/CMakeLists.txt +++ b/share/qtcreator/CMakeLists.txt @@ -28,6 +28,10 @@ qtc_copy_to_builddir(copy_share_to_builddir ) # create install rule for resource directories -install(DIRECTORY ${resource_directories} DESTINATION "${IDE_DATA_PATH}") +install( + DIRECTORY ${resource_directories} + DESTINATION "${IDE_DATA_PATH}" + USE_SOURCE_PERMISSIONS +) add_subdirectory(translations) diff --git a/share/qtcreator/debugger/stdtypes.py b/share/qtcreator/debugger/stdtypes.py index 0d8623e89b3..4de5baf4f91 100644 --- a/share/qtcreator/debugger/stdtypes.py +++ b/share/qtcreator/debugger/stdtypes.py @@ -729,13 +729,24 @@ def qdumpHelper__std__string__QNX(d, value, charType, format): def qdumpHelper__std__string__MSVC(d, value, charType, format): - (proxy, buffer, size, alloc) = value.split("p16spp") + try: + (proxy, buffer, size, alloc) = value.split("p16spp") + d.check(0 <= size and size <= alloc and alloc <= 100 * 1000 * 1000) + except RuntimeError: + proxy = None + (buffer, size, alloc) = value.split("16spp") + d.check(0 <= size and size <= alloc and alloc <= 100 * 1000 * 1000) _BUF_SIZE = int(16 / charType.size()) - d.check(0 <= size and size <= alloc and alloc <= 100 * 1000 * 1000) if _BUF_SIZE <= alloc: - (proxy, data) = value.split("pp") + if proxy is None: + data = value.extractPointer() + else: + (proxy, data) = value.split("pp") else: - data = value.address() + d.ptrSize() + if proxy is None: + data = value.address() + else: + data = value.address() + d.ptrSize() d.putCharArrayHelper(data, size, charType, format) @@ -1098,8 +1109,18 @@ def qdumpHelper__std__vector__QNX(d, value): (proxy, start, last, end) = value.split("pppp") size = (last - start) // innerType.size() - d.check(0 <= size and size <= 1000 * 1000 * 1000) - d.check(last <= end) + try: + d.check(0 <= size and size <= 1000 * 1000 * 1000) + d.check(last <= end) + except RuntimeError: + if isBool: + (start, last, end, size) = value.split("pppi") + else: + (start, last, end) = value.split("ppp") + size = (last - start) // innerType.size() + d.check(0 <= size and size <= 1000 * 1000 * 1000) + d.check(last <= end) + if size > 0: d.checkPointer(start) d.checkPointer(last) diff --git a/share/qtcreator/qml/qmlpuppet/commands/createscenecommand.cpp b/share/qtcreator/qml/qmlpuppet/commands/createscenecommand.cpp index 1ee34ff4477..da86573a7a5 100644 --- a/share/qtcreator/qml/qmlpuppet/commands/createscenecommand.cpp +++ b/share/qtcreator/qml/qmlpuppet/commands/createscenecommand.cpp @@ -29,136 +29,20 @@ namespace QmlDesigner { -CreateSceneCommand::CreateSceneCommand() = default; - -CreateSceneCommand::CreateSceneCommand(const QVector &instanceContainer, - const QVector &reparentContainer, - const QVector &idVector, - const QVector &valueChangeVector, - const QVector &bindingChangeVector, - const QVector &auxiliaryChangeVector, - const QVector &importVector, - const QVector &mockupTypeVector, - const QUrl &fileUrl, - const QHash &edit3dToolStates, - const QString &language) - : m_instanceVector(instanceContainer), - m_reparentInstanceVector(reparentContainer), - m_idVector(idVector), - m_valueChangeVector(valueChangeVector), - m_bindingChangeVector(bindingChangeVector), - m_auxiliaryChangeVector(auxiliaryChangeVector), - m_importVector(importVector), - m_mockupTypeVector(mockupTypeVector), - m_fileUrl(fileUrl), - m_edit3dToolStates(edit3dToolStates), - m_language(language) -{ -} - -QVector CreateSceneCommand::instances() const -{ - return m_instanceVector; -} - -QVector CreateSceneCommand::reparentInstances() const -{ - return m_reparentInstanceVector; -} - -QVector CreateSceneCommand::ids() const -{ - return m_idVector; -} - -QVector CreateSceneCommand::valueChanges() const -{ - return m_valueChangeVector; -} - -QVector CreateSceneCommand::bindingChanges() const -{ - return m_bindingChangeVector; -} - -QVector CreateSceneCommand::auxiliaryChanges() const -{ - return m_auxiliaryChangeVector; -} - -QVector CreateSceneCommand::imports() const -{ - return m_importVector; -} - -QVector CreateSceneCommand::mockupTypes() const -{ - return m_mockupTypeVector; -} - -QUrl CreateSceneCommand::fileUrl() const -{ - return m_fileUrl; -} - -QHash CreateSceneCommand::edit3dToolStates() const -{ - return m_edit3dToolStates; -} - -QString CreateSceneCommand::language() const -{ - return m_language; -} - -QDataStream &operator<<(QDataStream &out, const CreateSceneCommand &command) -{ - out << command.instances(); - out << command.reparentInstances(); - out << command.ids(); - out << command.valueChanges(); - out << command.bindingChanges(); - out << command.auxiliaryChanges(); - out << command.imports(); - out << command.mockupTypes(); - out << command.fileUrl(); - out << command.edit3dToolStates(); - out << command.language(); - - return out; -} - -QDataStream &operator>>(QDataStream &in, CreateSceneCommand &command) -{ - in >> command.m_instanceVector; - in >> command.m_reparentInstanceVector; - in >> command.m_idVector; - in >> command.m_valueChangeVector; - in >> command.m_bindingChangeVector; - in >> command.m_auxiliaryChangeVector; - in >> command.m_importVector; - in >> command.m_mockupTypeVector; - in >> command.m_fileUrl; - in >> command.m_edit3dToolStates; - in >> command.m_language; - - return in; -} - QDebug operator <<(QDebug debug, const CreateSceneCommand &command) { return debug.nospace() << "CreateSceneCommand(" - << "instances: " << command.instances() << ", " - << "reparentInstances: " << command.reparentInstances() << ", " - << "ids: " << command.ids() << ", " - << "valueChanges: " << command.valueChanges() << ", " - << "bindingChanges: " << command.bindingChanges() << ", " - << "auxiliaryChanges: " << command.auxiliaryChanges() << ", " - << "imports: " << command.imports() << ", " - << "mockupTypes: " << command.mockupTypes() << ", " - << "fileUrl: " << command.fileUrl() << ", " - << "edit3dToolStates: " << command.edit3dToolStates() << ", " - << "language: " << command.language() << ")"; + << "instances: " << command.instances << ", " + << "reparentInstances: " << command.reparentInstances << ", " + << "ids: " << command.ids << ", " + << "valueChanges: " << command.valueChanges << ", " + << "bindingChanges: " << command.bindingChanges << ", " + << "auxiliaryChanges: " << command.auxiliaryChanges << ", " + << "imports: " << command.imports << ", " + << "mockupTypes: " << command.mockupTypes << ", " + << "fileUrl: " << command.fileUrl << ", " + << "edit3dToolStates: " << command.edit3dToolStates << ", " + << "language: " << command.language << ")"; } } diff --git a/share/qtcreator/qml/qmlpuppet/commands/createscenecommand.h b/share/qtcreator/qml/qmlpuppet/commands/createscenecommand.h index aee8fe0d478..021d43a60ef 100644 --- a/share/qtcreator/qml/qmlpuppet/commands/createscenecommand.h +++ b/share/qtcreator/qml/qmlpuppet/commands/createscenecommand.h @@ -41,53 +41,87 @@ namespace QmlDesigner { class CreateSceneCommand { - friend QDataStream &operator>>(QDataStream &in, CreateSceneCommand &command); +public: + CreateSceneCommand() = default; + explicit CreateSceneCommand(const QVector &instanceContainer, + const QVector &reparentContainer, + const QVector &idVector, + const QVector &valueChangeVector, + const QVector &bindingChangeVector, + const QVector &auxiliaryChangeVector, + const QVector &importVector, + const QVector &mockupTypeVector, + const QUrl &fileUrl, + const QHash &edit3dToolStates, + const QString &language, + qint32 stateInstanceId) + : instances(instanceContainer) + , reparentInstances(reparentContainer) + , ids(idVector) + , valueChanges(valueChangeVector) + , bindingChanges(bindingChangeVector) + , auxiliaryChanges(auxiliaryChangeVector) + , imports(importVector) + , mockupTypes(mockupTypeVector) + , fileUrl(fileUrl) + , edit3dToolStates(edit3dToolStates) + , language(language) + , stateInstanceId{stateInstanceId} + {} + + friend QDataStream &operator<<(QDataStream &out, const CreateSceneCommand &command) + { + out << command.instances; + out << command.reparentInstances; + out << command.ids; + out << command.valueChanges; + out << command.bindingChanges; + out << command.auxiliaryChanges; + out << command.imports; + out << command.mockupTypes; + out << command.fileUrl; + out << command.edit3dToolStates; + out << command.language; + out << command.stateInstanceId; + + return out; + } + + friend QDataStream &operator>>(QDataStream &in, CreateSceneCommand &command) + { + in >> command.instances; + in >> command.reparentInstances; + in >> command.ids; + in >> command.valueChanges; + in >> command.bindingChanges; + in >> command.auxiliaryChanges; + in >> command.imports; + in >> command.mockupTypes; + in >> command.fileUrl; + in >> command.edit3dToolStates; + in >> command.language; + in >> command.stateInstanceId; + + return in; + } public: - CreateSceneCommand(); - explicit CreateSceneCommand( - const QVector &instanceContainer, - const QVector &reparentContainer, - const QVector &idVector, - const QVector &valueChangeVector, - const QVector &bindingChangeVector, - const QVector &auxiliaryChangeVector, - const QVector &importVector, - const QVector &mockupTypeVector, - const QUrl &fileUrl, - const QHash &edit3dToolStates, - const QString &language); - - QVector instances() const; - QVector reparentInstances() const; - QVector ids() const; - QVector valueChanges() const; - QVector bindingChanges() const; - QVector auxiliaryChanges() const; - QVector imports() const; - QVector mockupTypes() const; - QUrl fileUrl() const; - QHash edit3dToolStates() const; - QString language() const; - -private: - QVector m_instanceVector; - QVector m_reparentInstanceVector; - QVector m_idVector; - QVector m_valueChangeVector; - QVector m_bindingChangeVector; - QVector m_auxiliaryChangeVector; - QVector m_importVector; - QVector m_mockupTypeVector; - QUrl m_fileUrl; - QHash m_edit3dToolStates; - QString m_language; + QVector instances; + QVector reparentInstances; + QVector ids; + QVector valueChanges; + QVector bindingChanges; + QVector auxiliaryChanges; + QVector imports; + QVector mockupTypes; + QUrl fileUrl; + QHash edit3dToolStates; + QString language; + qint32 stateInstanceId = 0; }; -QDataStream &operator<<(QDataStream &out, const CreateSceneCommand &command); -QDataStream &operator>>(QDataStream &in, CreateSceneCommand &command); +QDebug operator<<(QDebug debug, const CreateSceneCommand &command); -QDebug operator <<(QDebug debug, const CreateSceneCommand &command); -} +} // namespace QmlDesigner Q_DECLARE_METATYPE(QmlDesigner::CreateSceneCommand) diff --git a/share/qtcreator/qml/qmlpuppet/container/imagecontainer.cpp b/share/qtcreator/qml/qmlpuppet/container/imagecontainer.cpp index 8348cbecb0c..8fbbbc48cf7 100644 --- a/share/qtcreator/qml/qmlpuppet/container/imagecontainer.cpp +++ b/share/qtcreator/qml/qmlpuppet/container/imagecontainer.cpp @@ -128,15 +128,16 @@ static void writeSharedMemory(SharedMemory *sharedMemory, const QImage &image) { sharedMemory->lock(); - qint32 headerData[5]; + qint32 headerData[6]; headerData[0] = qint32(image.sizeInBytes()); headerData[1] = image.bytesPerLine(); headerData[2] = image.size().width(); headerData[3] = image.size().height(); headerData[4] = image.format(); + headerData[5] = image.devicePixelRatio() * 100; - std::memcpy(sharedMemory->data(), headerData, 20); - std::memcpy(reinterpret_cast(sharedMemory->data()) + 20, image.constBits(), image.sizeInBytes()); + std::memcpy(sharedMemory->data(), headerData, 24); + std::memcpy(reinterpret_cast(sharedMemory->data()) + 24, image.constBits(), image.sizeInBytes()); sharedMemory->unlock(); } @@ -146,12 +147,13 @@ static void writeStream(QDataStream &out, const QImage &image) out << image.size(); out << qint32(image.format()); out << qint32(image.sizeInBytes()); + out << qint32(image.devicePixelRatio() * 100); out.writeRawData(reinterpret_cast(image.constBits()), image.sizeInBytes()); } QDataStream &operator<<(QDataStream &out, const ImageContainer &container) { - const int extraDataSize = 20; + const int extraDataSize = 24; static const bool dontUseSharedMemory = qEnvironmentVariableIsSet("DESIGNER_DONT_USE_SHARED_MEMORY"); out << container.instanceId(); @@ -183,24 +185,26 @@ static void readSharedMemory(qint32 key, ImageContainer &container) bool canAttach = sharedMemory.attach(QSharedMemory::ReadOnly); - if (canAttach && sharedMemory.size() >= 20) + if (canAttach && sharedMemory.size() >= 24) { sharedMemory.lock(); - qint32 headerData[5]; - std::memcpy(headerData, sharedMemory.constData(), 20); + qint32 headerData[6]; + std::memcpy(headerData, sharedMemory.constData(), 24); qint32 byteCount = headerData[0]; // qint32 bytesPerLine = headerData[1]; qint32 imageWidth = headerData[2]; qint32 imageHeight = headerData[3]; qint32 imageFormat = headerData[4]; + qreal pixelRatio = headerData[5] / 100.0; QImage image = QImage(imageWidth, imageHeight, QImage::Format(imageFormat)); + image.setDevicePixelRatio(pixelRatio); if (image.isNull()) qDebug() << Q_FUNC_INFO << "Not able to create image:" << imageWidth << imageHeight << imageFormat; else - std::memcpy(image.bits(), reinterpret_cast(sharedMemory.constData()) + 5, byteCount); + std::memcpy(image.bits(), reinterpret_cast(sharedMemory.constData()) + 6, byteCount); container.setImage(image); @@ -215,6 +219,7 @@ static void readStream(QDataStream &in, ImageContainer &container) qint32 bytesPerLine; QSize imageSize; qint32 imageFormat; + qint32 pixelRatio; in >> bytesPerLine; in >> imageSize; @@ -224,6 +229,7 @@ static void readStream(QDataStream &in, ImageContainer &container) QImage image = QImage(imageSize, QImage::Format(imageFormat)); in.readRawData(reinterpret_cast(image.bits()), byteCount); + image.setDevicePixelRatio(pixelRatio / 100.0); container.setImage(image); } diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.cpp index 39add144fb3..552d3232473 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.cpp @@ -318,12 +318,13 @@ void NodeInstanceServer::stopRenderTimer() void NodeInstanceServer::createScene(const CreateSceneCommand &command) { - setTranslationLanguage(command.language()); + setTranslationLanguage(command.language); initializeView(); Internal::QmlPrivateGate::stopUnifiedTimer(); setupScene(command); + setupState(command.stateInstanceId); refreshBindings(); startRenderTimer(); } @@ -399,15 +400,7 @@ void NodeInstanceServer::reparentInstances(const ReparentInstancesCommand &comma void NodeInstanceServer::changeState(const ChangeStateCommand &command) { - if (hasInstanceForId(command.stateInstanceId())) { - if (activeStateInstance().isValid()) - activeStateInstance().deactivateState(); - ServerNodeInstance instance = instanceForId(command.stateInstanceId()); - instance.activateState(); - } else { - if (activeStateInstance().isValid()) - activeStateInstance().deactivateState(); - } + setupState(command.stateInstanceId()); startRenderTimer(); } @@ -569,38 +562,37 @@ void NodeInstanceServer::setupDefaultDummyData() QList NodeInstanceServer::setupInstances(const CreateSceneCommand &command) { - QList instanceList = createInstances(command.instances()); + QList instanceList = createInstances(command.instances); - foreach (const IdContainer &container, command.ids()) { + for (const IdContainer &container : std::as_const(command.ids)) { if (hasInstanceForId(container.instanceId())) instanceForId(container.instanceId()).setId(container.id()); } - foreach (const PropertyValueContainer &container, command.valueChanges()) { + for (const PropertyValueContainer &container : std::as_const(command.valueChanges)) { if (container.isDynamic()) setInstancePropertyVariant(container); } - foreach (const PropertyValueContainer &container, command.valueChanges()) { + for (const PropertyValueContainer &container : std::as_const(command.valueChanges)) { if (!container.isDynamic()) setInstancePropertyVariant(container); } - reparentInstances(command.reparentInstances()); + reparentInstances(command.reparentInstances); - foreach (const PropertyBindingContainer &container, command.bindingChanges()) { + for (const PropertyBindingContainer &container : std::as_const(command.bindingChanges)) { if (container.isDynamic()) setInstancePropertyBinding(container); } - foreach (const PropertyBindingContainer &container, command.bindingChanges()) { + for (const PropertyBindingContainer &container : std::as_const(command.bindingChanges)) { if (!container.isDynamic()) setInstancePropertyBinding(container); } - foreach (const PropertyValueContainer &container, command.auxiliaryChanges()) { + for (const PropertyValueContainer &container : std::as_const(command.auxiliaryChanges)) setInstanceAuxiliaryData(container); - } for (int i = instanceList.size(); --i >= 0; ) instanceList[i].doComponentComplete(); @@ -1498,4 +1490,17 @@ void NodeInstanceServer::handleInstanceHidden(const ServerNodeInstance &/*instan { } +void NodeInstanceServer::setupState(qint32 stateInstanceId) +{ + if (hasInstanceForId(stateInstanceId)) { + if (activeStateInstance().isValid()) + activeStateInstance().deactivateState(); + ServerNodeInstance instance = instanceForId(stateInstanceId); + instance.activateState(); + } else { + if (activeStateInstance().isValid()) + activeStateInstance().deactivateState(); + } +} + } // namespace QmlDesigner diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.h b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.h index 1d1533884db..021a2bd6d0d 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.h +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.h @@ -289,6 +289,7 @@ protected: static QList allSubObjectsForObject(QObject *object); virtual void resizeCanvasSizeToRootItemSize() = 0; + void setupState(qint32 stateInstanceId); private: void setupOnlyWorkingImports(const QStringList &workingImportStatementList); diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp index 99dbe5ffe1b..576e53c5301 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp @@ -583,7 +583,8 @@ void Qt5InformationNodeInstanceServer::renderModelNodeImageView() void Qt5InformationNodeInstanceServer::doRenderModelNodeImageView() { - + // Disable preview in Qt6 until QTBUG-QTBUG-88320 is fixed +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) ServerNodeInstance instance; if (m_modelNodePreviewImageCommand.renderItemId() >= 0) instance = instanceForId(m_modelNodePreviewImageCommand.renderItemId()); @@ -594,6 +595,7 @@ void Qt5InformationNodeInstanceServer::doRenderModelNodeImageView() doRenderModelNode3DImageView(); else if (instance.isSubclassOf("QQuickItem")) doRenderModelNode2DImageView(); +#endif } void Qt5InformationNodeInstanceServer::doRenderModelNode3DImageView() @@ -1316,8 +1318,7 @@ void Qt5InformationNodeInstanceServer::createScene(const CreateSceneCommand &com Qt5NodeInstanceServer::createScene(command); QList instanceList; - const auto instances = command.instances(); - for (const InstanceContainer &container : instances) { + for (const InstanceContainer &container : std::as_const(command.instances)) { if (hasInstanceForId(container.instanceId())) { ServerNodeInstance instance = instanceForId(container.instanceId()); if (instance.isValid()) @@ -1331,7 +1332,7 @@ void Qt5InformationNodeInstanceServer::createScene(const CreateSceneCommand &com nodeInstanceClient()->componentCompleted(createComponentCompletedCommand(instanceList)); if (isQuick3DMode()) - setup3DEditView(instanceList, command.edit3dToolStates()); + setup3DEditView(instanceList, command.edit3dToolStates); QObject::connect(&m_renderModelNodeImageViewTimer, &QTimer::timeout, this, &Qt5InformationNodeInstanceServer::doRenderModelNodeImageView); @@ -1675,6 +1676,10 @@ void Qt5InformationNodeInstanceServer::handleInstanceLocked(const ServerNodeInst } } } +#else + Q_UNUSED(instance); + Q_UNUSED(enable); + Q_UNUSED(checkAncestors); #endif } @@ -1745,6 +1750,10 @@ void Qt5InformationNodeInstanceServer::handleInstanceHidden(const ServerNodeInst } } } +#else + Q_UNUSED(instance); + Q_UNUSED(enable); + Q_UNUSED(checkAncestors); #endif } diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5nodeinstanceserver.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5nodeinstanceserver.cpp index 3cc541545ea..90f959dd2be 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5nodeinstanceserver.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5nodeinstanceserver.cpp @@ -82,12 +82,6 @@ void Qt5NodeInstanceServer::initializeView() fileSelector->setExtraSelectors(customSelectors); } -#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) - // View needs to be shown for all puppets before any instances are created in case there is a View3D - quickView()->show(); - quickView()->lower(); -#endif - initializeAuxiliaryViews(); } @@ -116,11 +110,10 @@ void Qt5NodeInstanceServer::resetAllItems() void Qt5NodeInstanceServer::setupScene(const CreateSceneCommand &command) { - - setupMockupTypes(command.mockupTypes()); - setupFileUrl(command.fileUrl()); - setupImports(command.imports()); - setupDummyData(command.fileUrl()); + setupMockupTypes(command.mockupTypes); + setupFileUrl(command.fileUrl); + setupImports(command.imports); + setupDummyData(command.fileUrl); setupInstances(command); quickView()->resize(rootNodeInstance().boundingRect().size().toSize()); diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5previewnodeinstanceserver.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5previewnodeinstanceserver.cpp index 810c8f0dcf6..ae167ad6ca3 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5previewnodeinstanceserver.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5previewnodeinstanceserver.cpp @@ -46,7 +46,7 @@ Qt5PreviewNodeInstanceServer::Qt5PreviewNodeInstanceServer(NodeInstanceClientInt void Qt5PreviewNodeInstanceServer::createScene(const CreateSceneCommand &command) { - setTranslationLanguage(command.language()); + setTranslationLanguage(command.language); initializeView(); setupScene(command); startRenderTimer(); diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5rendernodeinstanceserver.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5rendernodeinstanceserver.cpp index 9722280dfa9..4a45c626be3 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5rendernodeinstanceserver.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5rendernodeinstanceserver.cpp @@ -137,7 +137,7 @@ void Qt5RenderNodeInstanceServer::createScene(const CreateSceneCommand &command) Qt5NodeInstanceServer::createScene(command); QList instanceList; - foreach (const InstanceContainer &container, command.instances()) { + for (const InstanceContainer &container : std::as_const(command.instances)) { if (hasInstanceForId(container.instanceId())) { ServerNodeInstance instance = instanceForId(container.instanceId()); if (instance.isValid()) { diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quickitemnodeinstance.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quickitemnodeinstance.cpp index 1c08b408e6e..b400d8c2d25 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quickitemnodeinstance.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quickitemnodeinstance.cpp @@ -187,7 +187,6 @@ void QuickItemNodeInstance::initialize(const ObjectNodeInstance::Pointer &object } ObjectNodeInstance::initialize(objectNodeInstance, flags); - quickItem()->update(); } QQuickItem *QuickItemNodeInstance::contentItem() const @@ -429,12 +428,14 @@ QImage QuickItemNodeInstance::renderImage() const nodeInstanceServer()->quickView()->afterRendering(); } + renderImage.setDevicePixelRatio(devicePixelRatio); #else renderImage = nodeInstanceServer()->quickView()->grabWindow(); + renderImage = renderImage.copy(renderBoundingRect.toRect()); + /* When grabbing an offscren window the device pixel ratio is 1 */ + renderImage.setDevicePixelRatio(1); #endif - renderImage.setDevicePixelRatio(devicePixelRatio); - return renderImage; } @@ -463,6 +464,7 @@ QImage QuickItemNodeInstance::renderPreviewImage(const QSize &previewImageSize) } #else image = nodeInstanceServer()->quickView()->grabWindow(); + image = image.copy(previewItemBoundingRect.toRect()); #endif image = image.scaledToWidth(size.width()); @@ -542,7 +544,9 @@ void QuickItemNodeInstance::updateDirtyNodesRecursive(QQuickItem *parentItem) co } QmlPrivateGate::disableNativeTextRendering(parentItem); +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) DesignerSupport::updateDirtyNode(parentItem); +#endif } void QuickItemNodeInstance::updateAllDirtyNodesRecursive(QQuickItem *parentItem) const diff --git a/share/qtcreator/templates/wizards/qtcreatorplugin/CMakeLists.txt b/share/qtcreator/templates/wizards/qtcreatorplugin/CMakeLists.txt new file mode 100644 index 00000000000..214dcfc2212 --- /dev/null +++ b/share/qtcreator/templates/wizards/qtcreatorplugin/CMakeLists.txt @@ -0,0 +1,32 @@ +cmake_minimum_required(VERSION 3.9) + +# Remove when sharing with others. +list(APPEND CMAKE_PREFIX_PATH "%{QtCreatorBuild}") + +project(%{PluginName}) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTORCC ON) +set(CMAKE_AUTOUIC ON) +set(CMAKE_CXX_STANDARD 17) + +find_package(QtCreator COMPONENTS Core REQUIRED) +find_package(QT NAMES Qt6 Qt5 COMPONENTS Widgets REQUIRED) +set(QtX Qt${QT_VERSION_MAJOR}) + +add_qtc_plugin(%{PluginName} + PLUGIN_DEPENDS + QtCreator::Core + DEPENDS + ${QtX}::Widgets + QtCreator::ExtensionSystem + QtCreator::Utils + SOURCES + .github/workflows/build_cmake.yml + .github/workflows/README.md + README.md + %{SrcFileName} + %{HdrFileName} + %{GlobalHdrFileName} + %{ConstantsHdrFileName} +) diff --git a/share/qtcreator/templates/wizards/qtcreatorplugin/README.md b/share/qtcreator/templates/wizards/qtcreatorplugin/README.md new file mode 100644 index 00000000000..bdd9b8a67d8 --- /dev/null +++ b/share/qtcreator/templates/wizards/qtcreatorplugin/README.md @@ -0,0 +1,35 @@ +# %{PluginName} + +## How to Build + +Create a build directory and run + + cmake -DCMAKE_PREFIX_PATH= -DCMAKE_BUILD_TYPE=RelWithDebInfo + cmake --build . + +where `` is the relative or absolute path to a Qt Creator build directory, or to +a combined binary and development package, and `` is the relative or absolute +path to this plugin directory. + +## How to Run + +Run a compatible Qt Creator with the additional command line argument + + -pluginpath + +where `` is the path to the resulting plugin library in the build directory +(`/lib/qtcreator/plugins` on Windows and Linux, +`/Qt Creator.app/Contents/PlugIns` on macOS). + +You might want to add `-temporarycleansettings` (or `-tcs`) to ensure that the opened Qt Creator +instance cannot mess with your user-global Qt Creator settings. + +When building and running the plugin from Qt Creator, you can use + + -pluginpath "%{buildDir}/lib/qtcreator/plugins" -tcs + +on Windows and Linux, or + + -pluginpath "%{buildDir}/Qt Creator.app/Contents/PlugIns" -tcs + +for the `Command line arguments` field in the run settings. diff --git a/share/qtcreator/templates/wizards/qtcreatorplugin/github_workflows_README.md b/share/qtcreator/templates/wizards/qtcreatorplugin/github_workflows_README.md index 8481ed15ae9..107410c6ec3 100644 --- a/share/qtcreator/templates/wizards/qtcreatorplugin/github_workflows_README.md +++ b/share/qtcreator/templates/wizards/qtcreatorplugin/github_workflows_README.md @@ -1,6 +1,6 @@ # GitHub Actions & Workflows -The `build_qmake.yml` in this directory adds a [GitHub action][1] and workflow that builds +The `build_cmake.yml` in this directory adds a [GitHub action][1] and workflow that builds your plugin anytime you push commits to GitHub on Windows, Linux and macOS. The build artifacts can be downloaded from GitHub and be installed into an existing Qt Creator diff --git a/share/qtcreator/templates/wizards/qtcreatorplugin/github_workflows_build_qmake.yml b/share/qtcreator/templates/wizards/qtcreatorplugin/github_workflows_build_cmake.yml similarity index 52% rename from share/qtcreator/templates/wizards/qtcreatorplugin/github_workflows_build_qmake.yml rename to share/qtcreator/templates/wizards/qtcreatorplugin/github_workflows_build_cmake.yml index 5326dfeb9da..bd5571b1d06 100644 --- a/share/qtcreator/templates/wizards/qtcreatorplugin/github_workflows_build_qmake.yml +++ b/share/qtcreator/templates/wizards/qtcreatorplugin/github_workflows_build_cmake.yml @@ -3,11 +3,12 @@ name: Build plugin on: [push] env: + PLUGIN_NAME: %{PluginName} QT_VERSION: %{JS: Util.qtVersion()} QT_CREATOR_VERSION: %{JS: Util.qtCreatorVersion()} QT_CREATOR_SNAPSHOT: NO - PLUGIN_PRO: %{ProFile} - PLUGIN_NAME: %{PluginName} + CMAKE_VERSION: 3.18.3 + NINJA_VERSION: 1.10.1 jobs: build: @@ -17,82 +18,114 @@ jobs: matrix: config: - { - name: "Windows Latest x64", artifact: "Windows-x64.zip", + name: "Windows Latest MSVC", artifact: "Windows-x64", os: windows-latest, - environment_script: "C:/Program Files (x86)/Microsoft Visual Studio/2019/Enterprise/VC/Auxiliary/Build/vcvars64.bat" + cc: "cl", cxx: "cl", + environment_script: "C:/Program Files (x86)/Microsoft Visual Studio/2019/Enterprise/VC/Auxiliary/Build/vcvars64.bat", } - { - name: "Windows Latest x86", artifact: "Windows-x86.zip", - os: windows-latest, - environment_script: "C:/Program Files (x86)/Microsoft Visual Studio/2019/Enterprise/VC/Auxiliary/Build/vcvars32.bat" + name: "Ubuntu Latest GCC", artifact: "Linux-x64", + os: ubuntu-latest, + cc: "gcc", cxx: "g++" } - { - name: "Linux Latest x64", artifact: "Linux-x64.zip", - os: ubuntu-latest - } - - { - name: "macOS Latest x64", artifact: "macOS-x64.zip", - os: macos-latest + name: "macOS Latest Clang", artifact: "macOS-x64", + os: macos-latest, + cc: "clang", cxx: "clang++" } steps: - uses: actions/checkout@v1 - - name: Installing system libs + - name: Download Ninja and CMake + shell: cmake -P {0} + run: | + set(cmake_version "$ENV{CMAKE_VERSION}") + set(ninja_version "$ENV{NINJA_VERSION}") + + if ("${{ runner.os }}" STREQUAL "Windows") + set(ninja_suffix "win.zip") + set(cmake_suffix "win64-x64.zip") + set(cmake_dir "cmake-${cmake_version}-win64-x64/bin") + elseif ("${{ runner.os }}" STREQUAL "Linux") + set(ninja_suffix "linux.zip") + set(cmake_suffix "Linux-x86_64.tar.gz") + set(cmake_dir "cmake-${cmake_version}-Linux-x86_64/bin") + elseif ("${{ runner.os }}" STREQUAL "macOS") + set(ninja_suffix "mac.zip") + set(cmake_suffix "Darwin-x86_64.tar.gz") + set(cmake_dir "cmake-${cmake_version}-Darwin-x86_64/CMake.app/Contents/bin") + endif() + + set(ninja_url "https://github.com/ninja-build/ninja/releases/download/v${ninja_version}/ninja-${ninja_suffix}") + file(DOWNLOAD "${ninja_url}" ./ninja.zip SHOW_PROGRESS) + execute_process(COMMAND ${CMAKE_COMMAND} -E tar xvf ./ninja.zip) + + set(cmake_url "https://github.com/Kitware/CMake/releases/download/v${cmake_version}/cmake-${cmake_version}-${cmake_suffix}") + file(DOWNLOAD "${cmake_url}" ./cmake.zip SHOW_PROGRESS) + execute_process(COMMAND ${CMAKE_COMMAND} -E tar xvf ./cmake.zip) + + # Add to PATH environment variable + file(TO_CMAKE_PATH "$ENV{GITHUB_WORKSPACE}/${cmake_dir}" cmake_dir) + set(path_separator ":") + if ("${{ runner.os }}" STREQUAL "Windows") + set(path_separator ";") + endif() + file(APPEND "$ENV{GITHUB_PATH}" "$ENV{GITHUB_WORKSPACE}${path_separator}${cmake_dir}") + + if (NOT "${{ runner.os }}" STREQUAL "Windows") + execute_process( + COMMAND chmod +x ninja + COMMAND chmod +x ${cmake_dir}/cmake + ) + endif() + + - name: Install system libs shell: cmake -P {0} run: | if ("${{ runner.os }}" STREQUAL "Linux") execute_process( - COMMAND sudo apt install libgl1-mesa-dev + COMMAND sudo apt update ) - elseif ("${{ runner.os }}" STREQUAL "Windows") - # get JOM - file(DOWNLOAD "https://download.qt.io/official_releases/jom/jom.zip" ./jom.zip SHOW_PROGRESS) - file(MAKE_DIRECTORY ./jom) - execute_process(COMMAND ${CMAKE_COMMAND} -E tar xvf ../jom.zip WORKING_DIRECTORY ./jom) + execute_process( + COMMAND sudo apt install libgl1-mesa-dev + RESULT_VARIABLE result + ) + if (NOT result EQUAL 0) + message(FATAL_ERROR "Failed to install dependencies") + endif() endif() - name: Download Qt id: qt shell: cmake -P {0} run: | - set(qt_version $ENV{QT_VERSION}) + set(qt_version "$ENV{QT_VERSION}") string(REPLACE "." "" qt_version_dotless "${qt_version}") if ("${{ runner.os }}" STREQUAL "Windows") set(url_os "windows_x86") - if ("${{ matrix.config.environment_script }}" MATCHES "vcvars64.bat") - set(qt_package_name "qt.qt5.${qt_version_dotless}.win64_msvc2019_64") - set(qt_dir_prefix "${qt_version}/msvc2019_64") - elseif ("${{ matrix.config.environment_script }}" MATCHES "vcvars32.bat") - set(qt_package_name "qt.qt5.${qt_version_dotless}.win32_msvc2019") - set(qt_dir_prefix "${qt_version}/msvc2019") - else() - endif() + set(qt_package_arch_suffix "win64_msvc2019_64") + set(qt_dir_prefix "${qt_version}/msvc2019_64") + set(qt_package_suffix "-Windows-Windows_10-MSVC2019-Windows-Windows_10-X86_64") elseif ("${{ runner.os }}" STREQUAL "Linux") set(url_os "linux_x64") - set(qt_package_name "qt.qt5.${qt_version_dotless}.gcc_64") + set(qt_package_arch_suffix "gcc_64") set(qt_dir_prefix "${qt_version}/gcc_64") + set(qt_package_suffix "-Linux-RHEL_7_6-GCC-Linux-RHEL_7_6-X86_64") elseif ("${{ runner.os }}" STREQUAL "macOS") set(url_os "mac_x64") - set(qt_package_name "qt.qt5.${qt_version_dotless}.clang_64") + set(qt_package_arch_suffix "clang_64") set(qt_dir_prefix "${qt_version}/clang_64") + set(qt_package_suffix "-MacOS-MacOS_10_13-Clang-MacOS-MacOS_10_13-X86_64") endif() set(qt_base_url "https://download.qt.io/online/qtsdkrepository/${url_os}/desktop/qt5_${qt_version_dotless}") file(DOWNLOAD "${qt_base_url}/Updates.xml" ./Updates.xml SHOW_PROGRESS) file(READ ./Updates.xml updates_xml) - string(REGEX MATCH "${qt_package_name}.*([0-9+-.]+).*qtbase([a-zA-Z0-9_-]+).7z" - updates_xml_output "${updates_xml}") - set(package_version ${CMAKE_MATCH_1}) - set(package_suffix ${CMAKE_MATCH_2}) - string(REPLACE "-debug-symbols" "" package_suffix "${package_suffix}") - - # Workaround for CMake's greedy regex - if ("${{ matrix.config.environment_script }}" MATCHES "vcvars32.bat") - string(REPLACE "X86_64" "X86" package_suffix "${package_suffix}") - endif() + string(REGEX MATCH "qt.qt5.*([0-9+-.]+)" updates_xml_output "${updates_xml}") + set(qt_package_version ${CMAKE_MATCH_1}) file(MAKE_DIRECTORY qt5) @@ -100,20 +133,27 @@ jobs: file(TO_CMAKE_PATH "$ENV{GITHUB_WORKSPACE}/qt5/${qt_dir_prefix}" qt_dir) message("::set-output name=qt_dir::${qt_dir}") - foreach(package qtbase qtdeclarative qttools qtsvg) - file(DOWNLOAD - "${qt_base_url}/${qt_package_name}/${package_version}${package}${package_suffix}.7z" ./${package}.7z - SHOW_PROGRESS + message("Downloading Qt to ${qt_dir}") + function(downloadAndExtract url archive) + message("Downloading ${url}") + file(DOWNLOAD "${url}" ./${archive} SHOW_PROGRESS) + execute_process(COMMAND ${CMAKE_COMMAND} -E tar xvf ../${archive} WORKING_DIRECTORY qt5) + endfunction() + + foreach(package qtbase qtdeclarative) + downloadAndExtract( + "${qt_base_url}/qt.qt5.${qt_version_dotless}.${qt_package_arch_suffix}/${qt_package_version}${package}${qt_package_suffix}.7z" + ${package}.7z ) - execute_process(COMMAND ${CMAKE_COMMAND} -E tar xvf ../${package}.7z WORKING_DIRECTORY qt5) endforeach() - file(READ "qt5/${qt_dir_prefix}/mkspecs/qconfig.pri" qtconfig) - string(REPLACE "Enterprise" "OpenSource" qtconfig "${qtconfig}") - string(REPLACE "licheck.exe" "" qtconfig "${qtconfig}") - string(REPLACE "licheck64" "" qtconfig "${qtconfig}") - string(REPLACE "licheck_mac" "" qtconfig "${qtconfig}") - file(WRITE "qt5/${qt_dir_prefix}/mkspecs/qconfig.pri" "${qtconfig}") + # uic depends on libicu56.so + if ("${{ runner.os }}" STREQUAL "Linux") + downloadAndExtract( + "${qt_base_url}/qt.qt5.${qt_version_dotless}.${qt_package_arch_suffix}/${qt_package_version}icu-linux-Rhel7.2-x64.7z" + icu.7z + ) + endif() - name: Download Qt Creator id: qt_creator @@ -128,29 +168,21 @@ jobs: endif() if ("${{ runner.os }}" STREQUAL "Windows") - set(qtc_output_directory "qtcreator/lib/qtcreator/plugins") - set(qtc_binary_name "$ENV{PLUGIN_NAME}4.dll") - if ("${{ matrix.config.environment_script }}" MATCHES "vcvars64.bat") - set(qtc_platform "windows_x64") - elseif ("${{ matrix.config.environment_script }}" MATCHES "vcvars32.bat") - set(qtc_platform "windows_x86") - endif() + set(qtc_platform "windows_x64") elseif ("${{ runner.os }}" STREQUAL "Linux") - set(qtc_output_directory "qtcreator/lib/qtcreator/plugins") - set(qtc_binary_name "lib$ENV{PLUGIN_NAME}.so") set(qtc_platform "linux_x64") elseif ("${{ runner.os }}" STREQUAL "macOS") - set(qtc_output_directory "qtcreator/bin/Qt Creator.app/Contents/PlugIns") - set(qtc_binary_name "lib$ENV{PLUGIN_NAME}.dylib") set(qtc_platform "mac_x64") endif() + file(TO_CMAKE_PATH "$ENV{GITHUB_WORKSPACE}/qtcreator" qtc_dir) # Save the path for other steps - message("::set-output name=qtc_binary_name::${qtc_binary_name}") - message("::set-output name=qtc_output_directory::${qtc_output_directory}") + message("::set-output name=qtc_dir::${qtc_dir}") file(MAKE_DIRECTORY qtcreator) + message("Downloading Qt Creator from ${qtc_base_url}/${qtc_platform}") + foreach(package qtcreator qtcreator_dev) file(DOWNLOAD "${qtc_base_url}/${qtc_platform}/${package}.7z" ./${package}.7z SHOW_PROGRESS) @@ -158,18 +190,13 @@ jobs: ${CMAKE_COMMAND} -E tar xvf ../${package}.7z WORKING_DIRECTORY qtcreator) endforeach() - if ("${{ runner.os }}" STREQUAL "macOS") - execute_process( - COMMAND ${CMAKE_COMMAND} -E make_directory qtcreator/bin - COMMAND ${CMAKE_COMMAND} -E create_symlink - "$ENV{GITHUB_WORKSPACE}/qtcreator/Qt Creator.app" - "$ENV{GITHUB_WORKSPACE}/qtcreator/bin/Qt Creator.app" - ) - endif() - - name: Build shell: cmake -P {0} run: | + set(ENV{CC} ${{ matrix.config.cc }}) + set(ENV{CXX} ${{ matrix.config.cxx }}) + set(ENV{MACOSX_DEPLOYMENT_TARGET} "10.13") + if ("${{ runner.os }}" STREQUAL "Windows" AND NOT "x${{ matrix.config.environment_script }}" STREQUAL "x") execute_process( COMMAND "${{ matrix.config.environment_script }}" && set @@ -183,55 +210,32 @@ jobs: endforeach() endif() - file(TO_CMAKE_PATH "$ENV{GITHUB_WORKSPACE}/qtcreator" qtcreator_dir) + set(ENV{NINJA_STATUS} "[%f/%t %o/sec] ") execute_process( - COMMAND ${{ steps.qt.outputs.qt_dir }}/bin/qmake - $ENV{PLUGIN_PRO} - CONFIG+=release - IDE_SOURCE_TREE="${qtcreator_dir}" - IDE_BUILD_TREE="${qtcreator_dir}" + COMMAND python + -u + ${{ steps.qt_creator.outputs.qtc_dir }}/scripts/build_plugin.py + --name "$ENV{PLUGIN_NAME}-$ENV{QT_CREATOR_VERSION}-${{ matrix.config.artifact }}" + --src . + --build build + --qt-path "${{ steps.qt.outputs.qt_dir }}" + --qtc-path "${{ steps.qt_creator.outputs.qtc_dir }}" + --output-path "$ENV{GITHUB_WORKSPACE}" RESULT_VARIABLE result ) if (NOT result EQUAL 0) - message(FATAL_ERROR "Bad exit status") + string(REGEX MATCH "FAILED:.*$" error_message "${output}") + string(REPLACE "\\n" "%0A" error_message "${error_message}") + message("::error::${error_message}") + message(FATAL_ERROR "Build failed") endif() - if ("${{ runner.os }}" STREQUAL "Windows") - set(ENV{PATH} "${{ steps.qt.outputs.qt_dir }}/bin/;$ENV{PATH}") - else() - set(ENV{PATH} "${{ steps.qt.outputs.qt_dir }}/bin/:$ENV{PATH}") - set(ENV{LD_LIBRARY_PATH} "qtcreator/lib/Qt/lib:$ENV{LD_LIBRARY_PATH}") - endif() - - include(ProcessorCount) - ProcessorCount(N) - - set(make_program make -j ${N}) - if ("${{ runner.os }}" STREQUAL "Windows") - set(make_program "jom/jom") - endif() - - execute_process( - COMMAND ${make_program} - RESULT_VARIABLE result - ) - if (NOT result EQUAL 0) - message(FATAL_ERROR "Bad exit status") - endif() - - file(TO_CMAKE_PATH "$ENV{GITHUB_WORKSPACE}/$ENV{PLUGIN_NAME}-$ENV{QT_CREATOR_VERSION}-${{ matrix.config.artifact }}" artifact) - - execute_process(COMMAND - ${CMAKE_COMMAND} -E tar cvf ${artifact} --format=zip "${{ steps.qt_creator.outputs.qtc_binary_name }}" - WORKING_DIRECTORY "${{ steps.qt_creator.outputs.qtc_output_directory }}" - ) - - - uses: actions/upload-artifact@v1 + - uses: actions/upload-artifact@v2 id: upload_artifact with: - path: ./${{ env.PLUGIN_NAME }}-${{ env.QT_CREATOR_VERSION }}-${{ matrix.config.artifact }} - name: ${{ env.PLUGIN_NAME}}-${{ env.QT_CREATOR_VERSION }}-${{ matrix.config.artifact }} + path: ./${{ env.PLUGIN_NAME }}-${{ env.QT_CREATOR_VERSION }}-${{ matrix.config.artifact }}.7z + name: ${{ env.PLUGIN_NAME}}-${{ env.QT_CREATOR_VERSION }}-${{ matrix.config.artifact }}.7z release: if: contains(github.ref, 'tags/v') @@ -268,19 +272,15 @@ jobs: matrix: config: - { - name: "Windows Latest x64", artifact: "Windows-x64.zip", + name: "Windows Latest x64", artifact: "Windows-x64.7z", os: ubuntu-latest } - { - name: "Windows Latest x86", artifact: "Windows-x86.zip", + name: "Linux Latest x64", artifact: "Linux-x64.7z", os: ubuntu-latest } - { - name: "Linux Latest x64", artifact: "Linux-x64.zip", - os: ubuntu-latest - } - - { - name: "macOS Latest x64", artifact: "macOS-x64.zip", + name: "macOS Latest x64", artifact: "macOS-x64.7z", os: macos-latest } needs: release @@ -311,4 +311,4 @@ jobs: upload_url: ${{ steps.set_upload_url.outputs.upload_url }} asset_path: ./${{ env.PLUGIN_NAME }}-${{ env.QT_CREATOR_VERSION }}-${{ matrix.config.artifact }} asset_name: ${{ env.PLUGIN_NAME }}-${{ env.QT_CREATOR_VERSION }}-${{ matrix.config.artifact }} - asset_content_type: application/zip + asset_content_type: application/x-7z-compressed diff --git a/share/qtcreator/templates/wizards/qtcreatorplugin/myplugin.pro b/share/qtcreator/templates/wizards/qtcreatorplugin/myplugin.pro deleted file mode 100644 index 34eed0aeeaa..00000000000 --- a/share/qtcreator/templates/wizards/qtcreatorplugin/myplugin.pro +++ /dev/null @@ -1,53 +0,0 @@ -DEFINES += %{LibraryDefine} - -# %{PluginName} files - -SOURCES += \\ - %{SrcFileName} - -HEADERS += \\ - %{HdrFileName} \\ - %{GlobalHdrFileName} \\ - %{ConstantsHdrFileName} - -DISTFILES += \\ - .github/workflows/build_qmake.yml \\ - .github/workflows/README.md - -# Qt Creator linking - -## Either set the IDE_SOURCE_TREE when running qmake, -## or set the QTC_SOURCE environment variable, to override the default setting -isEmpty(IDE_SOURCE_TREE): IDE_SOURCE_TREE = $$(QTC_SOURCE) -isEmpty(IDE_SOURCE_TREE): IDE_SOURCE_TREE = "%{QtCreatorSources}" - -## Either set the IDE_BUILD_TREE when running qmake, -## or set the QTC_BUILD environment variable, to override the default setting -isEmpty(IDE_BUILD_TREE): IDE_BUILD_TREE = $$(QTC_BUILD) -isEmpty(IDE_BUILD_TREE): IDE_BUILD_TREE = "%{QtCreatorBuild}" - -## uncomment to build plugin into user config directory -## /plugins/ -## where is e.g. -## "%LOCALAPPDATA%\QtProject\qtcreator" on Windows Vista and later -## "$XDG_DATA_HOME/data/QtProject/qtcreator" or "~/.local/share/data/QtProject/qtcreator" on Linux -## "~/Library/Application Support/QtProject/Qt Creator" on OS X -%{DestDir}USE_USER_DESTDIR = yes - -###### If the plugin can be depended upon by other plugins, this code needs to be outsourced to -###### _dependencies.pri, where is the name of the directory containing the -###### plugin's sources. - -QTC_PLUGIN_NAME = %{PluginName} -QTC_LIB_DEPENDS += \\ - # nothing here at this time - -QTC_PLUGIN_DEPENDS += \\ - coreplugin - -QTC_PLUGIN_RECOMMENDS += \\ - # optional plugin dependencies. nothing here at this time - -###### End _dependencies.pri contents ###### - -include($$IDE_SOURCE_TREE/src/qtcreatorplugin.pri) diff --git a/share/qtcreator/templates/wizards/qtcreatorplugin/wizard.json b/share/qtcreator/templates/wizards/qtcreatorplugin/wizard.json index 443fa25c250..6a629f0d05e 100644 --- a/share/qtcreator/templates/wizards/qtcreatorplugin/wizard.json +++ b/share/qtcreator/templates/wizards/qtcreatorplugin/wizard.json @@ -8,13 +8,12 @@ "trDisplayCategory": "Library", "icon": "qtcreatorplugin.png", "featuresRequired": [ "QtSupport.Wizards.FeatureQt", "QtSupport.Wizards.FeatureDesktop" ], - "enabled": "%{JS: value('Plugins').indexOf('QmakeProjectManager') >= 0}", + "enabled": "%{JS: value('Plugins').indexOf('CMakeProjectManager') >= 0}", "options": [ - { "key": "ProjectFile", "value": "%{ProFile}" }, + { "key": "ProjectFile", "value": "%{ProjectDirectory}/CMakeLists.txt" }, { "key": "PluginNameLower", "value": "%{JS: value('PluginName').toLowerCase()}"}, - { "key": "ProFile", "value": "%{JS: Util.fileName(value('PluginNameLower'), 'pro')}" }, { "key": "PluginJsonFile", "value": "%{JS: Util.fileName(value('PluginName'), 'json.in')}" }, { "key": "LibraryDefine", "value": "%{JS: Cpp.headerGuard(value('PluginName')) + '_LIBRARY'}" }, { "key": "LibraryExport", "value": "%{JS: Cpp.headerGuard(value('PluginName')) + '_EXPORT'}" }, @@ -115,17 +114,6 @@ "trText": "https://www.%{JS: encodeURIComponent(value('VendorName').toLowerCase())}.com" } }, - { - "name": "QtCreatorSources", - "persistenceKey": "QtCreatorSources", - "trDisplayName": "Qt Creator sources:", - "mandatory": true, - "type": "PathChooser", - "data": - { - "kind": "existingDirectory" - } - }, { "name": "QtCreatorBuild", "persistenceKey": "QtCreatorBuild", @@ -136,27 +124,6 @@ { "kind": "existingDirectory" } - }, - { - "name": "DestDir", - "persistenceKey": "QtCreatorPluginDestDir", - "trDisplayName": "Deploy into:", - "type": "ComboBox", - "data": - { - "index": 0, - "items": - [ - { - "trKey": "Qt Creator Build", - "value": "# " - }, - { - "trKey": "Local User Settings", - "value": "" - } - ] - } } ] }, @@ -185,13 +152,16 @@ "data": [ { - "source": "myplugin.pro", - "target": "%{ProFile}", + "source": "CMakeLists.txt", "openAsProject": true }, { - "source": "github_workflows_build_qmake.yml", - "target": ".github/workflows/build_qmake.yml" + "source": "README.md", + "openInEditor": true + }, + { + "source": "github_workflows_build_cmake.yml", + "target": ".github/workflows/build_cmake.yml" }, { "source": "github_workflows_README.md", @@ -199,8 +169,7 @@ }, { "source": "myplugin.cpp", - "target": "%{SrcFileName}", - "openInEditor": true + "target": "%{SrcFileName}" }, { "source": "myplugin.h", diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index dfc9c24cf7e..7e2f1c7e905 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -25,6 +25,7 @@ install( ${PROJECT_SOURCE_DIR}/scripts DESTINATION ./ COMPONENT Devel EXCLUDE_FROM_ALL + USE_SOURCE_PERMISSIONS ) install(EXPORT QtCreator @@ -70,7 +71,7 @@ export(EXPORT QtCreator FILE ${CMAKE_BINARY_DIR}/cmake/QtCreatorTargets.cmake) file(COPY - ${PROJECT_SOURCE_DIR}/cmake/QtCreatorIDEBranding.cmake + ${IDE_BRANDING_FILE} ${PROJECT_SOURCE_DIR}/cmake/QtCreatorTranslations.cmake ${PROJECT_SOURCE_DIR}/cmake/QtCreatorDocumentation.cmake ${PROJECT_SOURCE_DIR}/cmake/QtCreatorAPI.cmake @@ -83,7 +84,7 @@ file(COPY # Devel package install install( FILES - ${PROJECT_SOURCE_DIR}/cmake/QtCreatorIDEBranding.cmake + ${IDE_BRANDING_FILE} ${PROJECT_SOURCE_DIR}/cmake/QtCreatorTranslations.cmake ${PROJECT_SOURCE_DIR}/cmake/QtCreatorDocumentation.cmake ${PROJECT_SOURCE_DIR}/cmake/QtCreatorAPI.cmake diff --git a/src/app/CMakeLists.txt b/src/app/CMakeLists.txt index ce469f86aa7..0e52bde5dd3 100644 --- a/src/app/CMakeLists.txt +++ b/src/app/CMakeLists.txt @@ -66,10 +66,16 @@ if (APPLE) "${CMAKE_CURRENT_BINARY_DIR}/qtcreator.icns" "${CMAKE_CURRENT_BINARY_DIR}/qtcreator-project.icns" ) - set_source_files_properties( - "${CMAKE_CURRENT_BINARY_DIR}/qtcreator.icns" - "${CMAKE_CURRENT_BINARY_DIR}/qtcreator-project.icns" - PROPERTIES - MACOSX_PACKAGE_LOCATION "Resources" + qtc_copy_to_builddir(copy_icns + DESTINATION ${IDE_DATA_PATH} + FILES + ${CMAKE_CURRENT_BINARY_DIR}/qtcreator.icns + ${CMAKE_CURRENT_BINARY_DIR}/qtcreator-project.icns + ) + install( + FILES + ${CMAKE_CURRENT_BINARY_DIR}/qtcreator.icns + ${CMAKE_CURRENT_BINARY_DIR}/qtcreator-project.icns + DESTINATION ${IDE_DATA_PATH} ) endif() diff --git a/src/app/main.cpp b/src/app/main.cpp index 76a15ccb7d1..d18502e1f0a 100644 --- a/src/app/main.cpp +++ b/src/app/main.cpp @@ -341,11 +341,13 @@ static void setHighDpiEnvironmentVariable() && !qEnvironmentVariableIsSet("QT_AUTO_SCREEN_SCALE_FACTOR") && !qEnvironmentVariableIsSet("QT_SCALE_FACTOR") && !qEnvironmentVariableIsSet("QT_SCREEN_SCALE_FACTORS")) { +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); #if QT_VERSION == QT_VERSION_CHECK(5, 14, 0) // work around QTBUG-80934 QGuiApplication::setHighDpiScaleFactorRoundingPolicy( Qt::HighDpiScaleFactorRoundingPolicy::Round); +#endif #endif } } @@ -557,8 +559,8 @@ int main(int argc, char **argv) CrashHandlerSetup::EnableRestart, libexecPath); #endif - app.setAttribute(Qt::AA_UseHighDpiPixmaps); #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) + app.setAttribute(Qt::AA_UseHighDpiPixmaps); app.setAttribute(Qt::AA_DisableWindowContextHelpButton); #endif @@ -586,7 +588,7 @@ int main(int argc, char **argv) app.setProperty("qtc_locale", locale); break; } - translator.load(QString()); // unload() + Q_UNUSED(translator.load(QString())); // unload() } else if (locale == QLatin1String("C") /* overrideLanguage == "English" */) { // use built-in break; diff --git a/src/libs/3rdparty/yaml-cpp/include/yaml-cpp/node/detail/iterator.h b/src/libs/3rdparty/yaml-cpp/include/yaml-cpp/node/detail/iterator.h index deec8fb62cd..0ea3bc3f0e3 100644 --- a/src/libs/3rdparty/yaml-cpp/include/yaml-cpp/node/detail/iterator.h +++ b/src/libs/3rdparty/yaml-cpp/include/yaml-cpp/node/detail/iterator.h @@ -19,8 +19,7 @@ namespace detail { struct iterator_value; template -class iterator_base : public std::iterator { +class iterator_base { private: template @@ -37,7 +36,11 @@ class iterator_base : public std::iterator { }; template -class node_iterator_base - : public std::iterator, - std::ptrdiff_t, node_iterator_value*, - node_iterator_value> { +class node_iterator_base { private: struct enabler {}; @@ -70,7 +67,11 @@ class node_iterator_base public: typedef typename node_iterator_type::seq SeqIter; typedef typename node_iterator_type::map MapIter; - typedef node_iterator_value value_type; + using iterator_category = std::forward_iterator_tag; + using value_type = node_iterator_value; + using difference_type = std::ptrdiff_t; + using pointer = node_iterator_value*; + using reference = node_iterator_value&; node_iterator_base() : m_type(iterator_type::NoneType), m_seqIt(), m_mapIt(), m_mapEnd() {} diff --git a/src/libs/qmleditorwidgets/easingpane/easingcontextpane.cpp b/src/libs/qmleditorwidgets/easingpane/easingcontextpane.cpp index a794b337a08..7f7c4684dd5 100644 --- a/src/libs/qmleditorwidgets/easingpane/easingcontextpane.cpp +++ b/src/libs/qmleditorwidgets/easingpane/easingcontextpane.cpp @@ -26,6 +26,7 @@ #include "easingcontextpane.h" #include "ui_easingcontextpane.h" #include +#include #include #include @@ -287,8 +288,10 @@ void QmlEditorWidgets::EasingContextPane::on_durationSpinBox_valueChanged(int ne emit propertyChanged(QLatin1String("duration"), newValue); } -void QmlEditorWidgets::EasingContextPane::on_easingShapeComboBox_currentIndexChanged(const QString &newShape) +void QmlEditorWidgets::EasingContextPane::on_easingShapeComboBox_currentIndexChanged(int newIndex) { + QTC_ASSERT(newIndex >= 0, return); + const QString newShape = ui->easingShapeComboBox->itemText(newIndex); if (newShape==QLatin1String("Linear")) setLinear(); else if (newShape==QLatin1String("Bounce")) @@ -311,8 +314,10 @@ void QmlEditorWidgets::EasingContextPane::on_easingShapeComboBox_currentIndexCha } } -void QmlEditorWidgets::EasingContextPane::on_easingExtremesComboBox_currentIndexChanged(const QString &newExtremes) +void QmlEditorWidgets::EasingContextPane::on_easingExtremesComboBox_currentIndexChanged(int newIndex) { + QTC_ASSERT(newIndex >= 0, return); + const QString newExtremes = ui->easingExtremesComboBox->itemText(newIndex); if (m_easingGraph->easingExtremes() != newExtremes) { m_easingGraph->setEasingExtremes(newExtremes); m_easingGraph->setAmplitude(ui->amplitudeSpinBox->value()); diff --git a/src/libs/qmleditorwidgets/easingpane/easingcontextpane.h b/src/libs/qmleditorwidgets/easingpane/easingcontextpane.h index 3cab9523b5f..4c50bf08b3c 100644 --- a/src/libs/qmleditorwidgets/easingpane/easingcontextpane.h +++ b/src/libs/qmleditorwidgets/easingpane/easingcontextpane.h @@ -77,8 +77,8 @@ private slots: void on_overshootSpinBox_valueChanged(double); void on_periodSpinBox_valueChanged(double); void on_amplitudeSpinBox_valueChanged(double); - void on_easingExtremesComboBox_currentIndexChanged(const QString &); - void on_easingShapeComboBox_currentIndexChanged(const QString &); + void on_easingExtremesComboBox_currentIndexChanged(int); + void on_easingShapeComboBox_currentIndexChanged(int); void on_durationSpinBox_valueChanged(int); void switchToGraph(); diff --git a/src/libs/sqlite/sqlitedatabase.cpp b/src/libs/sqlite/sqlitedatabase.cpp index 084fd3dd1e0..f5c554548fa 100644 --- a/src/libs/sqlite/sqlitedatabase.cpp +++ b/src/libs/sqlite/sqlitedatabase.cpp @@ -151,6 +151,11 @@ void Database::applyAndUpdateSessions() m_statements->sessions.applyAndUpdateSessions(); } +SessionChangeSets Database::changeSets() const +{ + return m_statements->sessions.changeSets(); +} + const Utils::PathString &Database::databaseFilePath() const { return m_databaseFilePath; diff --git a/src/libs/sqlite/sqlitedatabase.h b/src/libs/sqlite/sqlitedatabase.h index 54836f01094..c62ab92e251 100644 --- a/src/libs/sqlite/sqlitedatabase.h +++ b/src/libs/sqlite/sqlitedatabase.h @@ -28,6 +28,7 @@ #include "sqlitedatabasebackend.h" #include "sqlitedatabaseinterface.h" #include "sqliteglobal.h" +#include "sqlitesessionchangeset.h" #include "sqlitetable.h" #include "sqlitetransaction.h" @@ -131,6 +132,8 @@ public: void setAttachedTables(const Utils::SmallStringVector &tables) override; void applyAndUpdateSessions() override; + SessionChangeSets changeSets() const; + private: void deferredBegin() override; void immediateBegin() override; diff --git a/src/libs/sqlite/sqlitesessionchangeset.cpp b/src/libs/sqlite/sqlitesessionchangeset.cpp index d348ac7bfce..bc18efaed7f 100644 --- a/src/libs/sqlite/sqlitesessionchangeset.cpp +++ b/src/libs/sqlite/sqlitesessionchangeset.cpp @@ -86,7 +86,7 @@ ValueView convertSqliteValue(sqlite3_value *value) return ValueView::create(sqlite3_value_double(value)); case SQLITE_TEXT: return ValueView::create( - Utils::SmallStringView{reinterpret_cast(sqlite3_value_text(value)), + Utils::SmallStringView{reinterpret_cast(sqlite3_value_text(value)), static_cast(sqlite3_value_bytes(value))}); case SQLITE_NULL: return ValueView::create(NullValue{}); diff --git a/src/libs/sqlite/sqlitesessionchangeset.h b/src/libs/sqlite/sqlitesessionchangeset.h index 8dc27d1ef8f..29f049e5fae 100644 --- a/src/libs/sqlite/sqlitesessionchangeset.h +++ b/src/libs/sqlite/sqlitesessionchangeset.h @@ -41,9 +41,10 @@ namespace Sqlite { class Sessions; -namespace SessionChangeSetInternal { enum class Operation : char { Invalid, Insert, Update, Delete }; +namespace SessionChangeSetInternal { + class SentinelIterator {}; @@ -54,7 +55,7 @@ public: ValueView oldValue; }; -class ConstTupleIterator +class SQLITE_EXPORT ConstTupleIterator { public: using difference_type = int; @@ -63,7 +64,9 @@ public: using reference = const ValueView &; using iterator_category = std::forward_iterator_tag; - ConstTupleIterator(sqlite3_changeset_iter *sessionIterator, int index, Operation operation) + ConstTupleIterator(sqlite3_changeset_iter *sessionIterator, + int index, + Sqlite::Operation operation) : m_sessionIterator{sessionIterator} , m_column{index} , m_operation{operation} @@ -91,10 +94,10 @@ public: private: sqlite3_changeset_iter *m_sessionIterator = {}; int m_column = 0; - Operation m_operation = Operation::Invalid; + Sqlite::Operation m_operation = Sqlite::Operation::Invalid; }; -class Tuple +class SQLITE_EXPORT Tuple { public: using difference_type = int; @@ -108,7 +111,7 @@ public: Utils::SmallStringView table; sqlite3_changeset_iter *sessionIterator = {}; int columnCount = 0; - Operation operation = Operation::Invalid; + Sqlite::Operation operation = Sqlite::Operation::Invalid; ValueViews operator[](int column) const; ConstTupleIterator begin() const { return {sessionIterator, 0, operation}; } @@ -117,7 +120,7 @@ public: enum class State : char { Invalid, Row, Done }; -class ConstIterator +class SQLITE_EXPORT ConstIterator { public: using difference_type = long; @@ -144,13 +147,19 @@ public: ConstIterator &operator=(ConstIterator &&other) { auto tmp = std::move(other); - std::swap(tmp, *this); + swap(tmp, *this); return *this; } ~ConstIterator(); + friend void swap(ConstIterator &first, ConstIterator &second) + { + std::swap(first.m_sessionIterator, second.m_sessionIterator); + std::swap(first.m_state, second.m_state); + } + ConstIterator &operator++(); friend bool operator==(const ConstIterator &first, const ConstIterator &second) diff --git a/src/libs/utils/runextensions.h b/src/libs/utils/runextensions.h index eacbd8dc4cd..779c2b7bc28 100644 --- a/src/libs/utils/runextensions.h +++ b/src/libs/utils/runextensions.h @@ -261,7 +261,7 @@ void runAsyncQFutureInterfaceDispatch(std::true_type, QFutureInterface void runAsyncQFutureInterfaceDispatch(std::false_type, QFutureInterface futureInterface, Function &&function, Args&&... args) { - runAsyncReturnVoidDispatch(std::is_void>(), + runAsyncReturnVoidDispatch(std::is_void>(), futureInterface, std::forward(function), std::forward(args)...); } diff --git a/src/plugins/android/androidconfigurations.h b/src/plugins/android/androidconfigurations.h index edfbfa2704b..3791acd8c84 100644 --- a/src/plugins/android/androidconfigurations.h +++ b/src/plugins/android/androidconfigurations.h @@ -39,7 +39,6 @@ #include #include #include -#include #include #include diff --git a/src/plugins/android/androidrunner.h b/src/plugins/android/androidrunner.h index e745305d321..b8b8d3468e9 100644 --- a/src/plugins/android/androidrunner.h +++ b/src/plugins/android/androidrunner.h @@ -31,7 +31,6 @@ #include #include -#include #include #include #include diff --git a/src/plugins/android/avddialog.cpp b/src/plugins/android/avddialog.cpp index cc932dc6b79..3f8e687d449 100644 --- a/src/plugins/android/avddialog.cpp +++ b/src/plugins/android/avddialog.cpp @@ -234,8 +234,9 @@ void AvdDialog::updateApiLevelComboBox() m_avdDialog.targetApiComboBox->clear(); for (SystemImage *image : filteredList) { QString imageString = "android-" % QString::number(image->apiLevel()); - if (image->sdkStylePath().contains("playstore")) - imageString += " (Google PlayStore)"; + const QStringList imageSplits = image->sdkStylePath().split(';'); + if (imageSplits.size() == 4) + imageString += QStringLiteral(" (%1)").arg(imageSplits.at(2)); m_avdDialog.targetApiComboBox->addItem(imageString, QVariant::fromValue(image)); m_avdDialog.targetApiComboBox->setItemData(m_avdDialog.targetApiComboBox->count() - 1, diff --git a/src/plugins/beautifier/beautifierplugin.cpp b/src/plugins/beautifier/beautifierplugin.cpp index 58e934098e1..f1f15da32c2 100644 --- a/src/plugins/beautifier/beautifierplugin.cpp +++ b/src/plugins/beautifier/beautifierplugin.cpp @@ -60,7 +60,6 @@ #include #include -#include #include #include #include diff --git a/src/plugins/clangformat/CMakeLists.txt b/src/plugins/clangformat/CMakeLists.txt index 3edaead7577..9e91349a3c3 100644 --- a/src/plugins/clangformat/CMakeLists.txt +++ b/src/plugins/clangformat/CMakeLists.txt @@ -1,5 +1,5 @@ add_qtc_plugin(ClangFormat - CONDITION TARGET libclang + CONDITION TARGET libclang AND LLVM_PACKAGE_VERSION VERSION_GREATER_EQUAL 10.0.0 DEPENDS Utils Qt5::Widgets clangFormat INCLUDES "${CLANG_INCLUDE_DIRS}" PLUGIN_DEPENDS Core TextEditor CppEditor CppTools ProjectExplorer diff --git a/src/plugins/clangformat/clangformatutils.cpp b/src/plugins/clangformat/clangformatutils.cpp index e0eb2827c4a..8e11c153647 100644 --- a/src/plugins/clangformat/clangformatutils.cpp +++ b/src/plugins/clangformat/clangformatutils.cpp @@ -115,7 +115,7 @@ static clang::format::FormatStyle qtcStyle() style.ExperimentalAutoDetectBinPacking = false; style.FixNamespaceComments = true; style.ForEachMacros = {"forever", "foreach", "Q_FOREACH", "BOOST_FOREACH"}; - style.IncludeStyle.IncludeCategories = {{"^ -#include -#include -#include #include +#include #include +#include namespace Core { class SearchResult; } diff --git a/src/plugins/clangtools/clangtoolruncontrol.h b/src/plugins/clangtools/clangtoolruncontrol.h index 9f46d0f2e38..ccf2f87468b 100644 --- a/src/plugins/clangtools/clangtoolruncontrol.h +++ b/src/plugins/clangtools/clangtoolruncontrol.h @@ -76,7 +76,7 @@ public: int filesAnalyzed() const { return m_filesAnalyzed.size(); } int filesNotAnalyzed() const { return m_filesNotAnalyzed.size(); } - int totalFilesToAnalyze() const { return m_fileInfos.size(); } + int totalFilesToAnalyze() const { return int(m_fileInfos.size()); } signals: void buildFailed(); diff --git a/src/plugins/coreplugin/dialogs/shortcutsettings.cpp b/src/plugins/coreplugin/dialogs/shortcutsettings.cpp index 46c4e6699dc..7b95dea3147 100644 --- a/src/plugins/coreplugin/dialogs/shortcutsettings.cpp +++ b/src/plugins/coreplugin/dialogs/shortcutsettings.cpp @@ -387,7 +387,7 @@ void ShortcutSettingsWidget::setupShortcutBox(ShortcutItem *scitem) }; const auto addButtonToLayout = [this, updateAddButton] { m_shortcutLayout->addWidget(m_addButton, - m_shortcutInputs.size() * 2 - 1, + int(m_shortcutInputs.size() * 2 - 1), m_shortcutLayout->columnCount() - 1); updateAddButton(); }; @@ -397,7 +397,7 @@ void ShortcutSettingsWidget::setupShortcutBox(ShortcutItem *scitem) for (int i = 0; i < qMax(1, scitem->m_keys.size()); ++i) addShortcutInput(i, scitem->m_keys.value(i)); connect(m_addButton, &QPushButton::clicked, this, [this, addShortcutInput, addButtonToLayout] { - addShortcutInput(m_shortcutInputs.size(), {}); + addShortcutInput(int(m_shortcutInputs.size()), {}); addButtonToLayout(); }); addButtonToLayout(); diff --git a/src/plugins/cppcheck/cppchecktool.h b/src/plugins/cppcheck/cppchecktool.h index cc5f77d2183..c10c2516e2f 100644 --- a/src/plugins/cppcheck/cppchecktool.h +++ b/src/plugins/cppcheck/cppchecktool.h @@ -27,7 +27,7 @@ #include -#include +#include #include #include diff --git a/src/plugins/cppeditor/cppeditorwidget.cpp b/src/plugins/cppeditor/cppeditorwidget.cpp index ad5a4b988f0..aa58f2b8962 100644 --- a/src/plugins/cppeditor/cppeditorwidget.cpp +++ b/src/plugins/cppeditor/cppeditorwidget.cpp @@ -91,7 +91,6 @@ #include #include #include -#include #include #include #include diff --git a/src/plugins/cppeditor/cppquickfix_test.cpp b/src/plugins/cppeditor/cppquickfix_test.cpp index 43befecb7db..c5a583d37c2 100644 --- a/src/plugins/cppeditor/cppquickfix_test.cpp +++ b/src/plugins/cppeditor/cppquickfix_test.cpp @@ -4370,20 +4370,25 @@ void CppEditorPlugin::test_quickfix_InsertDefFromDecl_templateClass() "template\n" "class Foo\n" "{\n" - " void fun@c();\n" - "};\n"; + " void fun@c1();\n" + " void func2();\n" + "};\n\n" + "template\n" + "void Foo::func2() {}\n"; QByteArray expected = "template\n" "class Foo\n" "{\n" - " void fun@c();\n" - "};\n" - "\n" + " void func1();\n" + " void func2();\n" + "};\n\n" "template\n" - "void Foo::func()\n" // Should really be Foo::func() + "void Foo::func1()\n" "{\n" "\n" - "}\n"; + "}\n\n" + "template\n" + "void Foo::func2() {}\n"; InsertDefFromDecl factory; QuickFixOperationTest(singleDocument(original, expected), &factory); @@ -4405,7 +4410,7 @@ void CppEditorPlugin::test_quickfix_InsertDefFromDecl_templateFunction() "};\n" "\n" "template\n" - "void Foo::func()\n" + "void Foo::func()\n" "{\n" "\n" "}\n"; diff --git a/src/plugins/cppeditor/cppquickfixes.cpp b/src/plugins/cppeditor/cppquickfixes.cpp index 9f85fd03c1c..1e44abc4367 100644 --- a/src/plugins/cppeditor/cppquickfixes.cpp +++ b/src/plugins/cppeditor/cppquickfixes.cpp @@ -3070,6 +3070,7 @@ public: oo.showReturnTypes = true; oo.showArgumentNames = true; oo.showEnclosingTemplate = true; + oo.showTemplateParameters = true; if (defPos == DefPosInsideClass) { const int targetPos = targetFile->position(loc.line(), loc.column()); diff --git a/src/plugins/cpptools/builtinindexingsupport.cpp b/src/plugins/cpptools/builtinindexingsupport.cpp index cfb3be635fe..99d50876a61 100644 --- a/src/plugins/cpptools/builtinindexingsupport.cpp +++ b/src/plugins/cpptools/builtinindexingsupport.cpp @@ -135,7 +135,6 @@ void classifyFiles(const QSet &files, QStringList *headers, QStringList } void indexFindErrors(QFutureInterface &indexingFuture, - const QFutureInterface &superFuture, const ParseParams params) { QStringList sources, headers; @@ -149,7 +148,7 @@ void indexFindErrors(QFutureInterface &indexingFuture, timer.start(); for (int i = 0, end = files.size(); i < end ; ++i) { - if (indexingFuture.isCanceled() || superFuture.isCanceled()) + if (indexingFuture.isCanceled()) break; const QString file = files.at(i); @@ -179,7 +178,6 @@ void indexFindErrors(QFutureInterface &indexingFuture, } void index(QFutureInterface &indexingFuture, - const QFutureInterface &superFuture, const ParseParams params) { QScopedPointer sourceProcessor(CppModelManager::createSourceProcessor()); @@ -209,7 +207,7 @@ void index(QFutureInterface &indexingFuture, qCDebug(indexerLog) << "About to index" << files.size() << "files."; for (int i = 0; i < files.size(); ++i) { - if (indexingFuture.isCanceled() || superFuture.isCanceled()) + if (indexingFuture.isCanceled()) break; const QString fileName = files.at(i); @@ -243,9 +241,7 @@ void index(QFutureInterface &indexingFuture, qCDebug(indexerLog) << "Indexing finished."; } -void parse(QFutureInterface &indexingFuture, - const QFutureInterface &superFuture, - const ParseParams params) +void parse(QFutureInterface &indexingFuture, const ParseParams params) { const QSet &files = params.sourceFiles; if (files.isEmpty()) @@ -254,9 +250,9 @@ void parse(QFutureInterface &indexingFuture, indexingFuture.setProgressRange(0, files.size()); if (FindErrorsIndexing) - indexFindErrors(indexingFuture, superFuture, params); + indexFindErrors(indexingFuture, params); else - index(indexingFuture, superFuture, params); + index(indexingFuture, params); indexingFuture.setProgressValue(files.size()); CppModelManager::instance()->finishedRefreshingSourceFiles(files); @@ -349,9 +345,7 @@ BuiltinIndexingSupport::BuiltinIndexingSupport() BuiltinIndexingSupport::~BuiltinIndexingSupport() = default; QFuture BuiltinIndexingSupport::refreshSourceFiles( - const QFutureInterface &superFuture, - const QSet &sourceFiles, - CppModelManager::ProgressNotificationMode mode) + const QSet &sourceFiles, CppModelManager::ProgressNotificationMode mode) { CppModelManager *mgr = CppModelManager::instance(); @@ -361,7 +355,7 @@ QFuture BuiltinIndexingSupport::refreshSourceFiles( params.workingCopy = mgr->workingCopy(); params.sourceFiles = sourceFiles; - QFuture result = Utils::runAsync(mgr->sharedThreadPool(), parse, superFuture, params); + QFuture result = Utils::runAsync(mgr->sharedThreadPool(), parse, params); if (m_synchronizer.futures().size() > 10) { QList > futures = m_synchronizer.futures(); diff --git a/src/plugins/cpptools/builtinindexingsupport.h b/src/plugins/cpptools/builtinindexingsupport.h index 26e0a22dd3b..9a61d60ec96 100644 --- a/src/plugins/cpptools/builtinindexingsupport.h +++ b/src/plugins/cpptools/builtinindexingsupport.h @@ -38,8 +38,7 @@ public: BuiltinIndexingSupport(); ~BuiltinIndexingSupport() override; - QFuture refreshSourceFiles(const QFutureInterface &superFuture, - const QSet &sourceFiles, + QFuture refreshSourceFiles(const QSet &sourceFiles, CppModelManager::ProgressNotificationMode mode) override; SymbolSearcher *createSymbolSearcher(const SymbolSearcher::Parameters ¶meters, const QSet &fileNames) override; diff --git a/src/plugins/cpptools/cppfindreferences.cpp b/src/plugins/cpptools/cppfindreferences.cpp index 18438934d09..52bf900dac8 100644 --- a/src/plugins/cpptools/cppfindreferences.cpp +++ b/src/plugins/cpptools/cppfindreferences.cpp @@ -48,6 +48,7 @@ #include #include #include +#include #include diff --git a/src/plugins/cpptools/cppfindreferences.h b/src/plugins/cpptools/cppfindreferences.h index ce831734449..a2e21438ac2 100644 --- a/src/plugins/cpptools/cppfindreferences.h +++ b/src/plugins/cpptools/cppfindreferences.h @@ -31,7 +31,6 @@ #include #include #include -#include QT_FORWARD_DECLARE_CLASS(QTimer) diff --git a/src/plugins/cpptools/cppindexingsupport.h b/src/plugins/cpptools/cppindexingsupport.h index e3d9eb257e2..1a77dc822c8 100644 --- a/src/plugins/cpptools/cppindexingsupport.h +++ b/src/plugins/cpptools/cppindexingsupport.h @@ -78,9 +78,9 @@ class CPPTOOLS_EXPORT CppIndexingSupport public: virtual ~CppIndexingSupport() = 0; - virtual QFuture refreshSourceFiles(const QFutureInterface &superFuture, - const QSet &sourceFiles, - CppModelManager::ProgressNotificationMode mode) = 0; + virtual QFuture refreshSourceFiles(const QSet &sourceFiles, + CppModelManager::ProgressNotificationMode mode) + = 0; virtual SymbolSearcher *createSymbolSearcher(const SymbolSearcher::Parameters ¶meters, const QSet &fileNames) = 0; }; diff --git a/src/plugins/cpptools/cppmodelmanager.cpp b/src/plugins/cpptools/cppmodelmanager.cpp index ca8fe286868..7315b303df8 100644 --- a/src/plugins/cpptools/cppmodelmanager.cpp +++ b/src/plugins/cpptools/cppmodelmanager.cpp @@ -929,14 +929,6 @@ static QSet tooBigFilesRemoved(const QSet &files, int fileSize QFuture CppModelManager::updateSourceFiles(const QSet &sourceFiles, ProgressNotificationMode mode) -{ - const QFutureInterface dummy; - return updateSourceFiles(dummy, sourceFiles, mode); -} - -QFuture CppModelManager::updateSourceFiles(const QFutureInterface &superFuture, - const QSet &sourceFiles, - ProgressNotificationMode mode) { if (sourceFiles.isEmpty() || !d->m_indexerEnabled) return QFuture(); @@ -944,8 +936,8 @@ QFuture CppModelManager::updateSourceFiles(const QFutureInterface &s const QSet filteredFiles = tooBigFilesRemoved(sourceFiles, indexerFileSizeLimitInMb()); if (d->m_indexingSupporter) - d->m_indexingSupporter->refreshSourceFiles(superFuture, filteredFiles, mode); - return d->m_internalIndexingSupport->refreshSourceFiles(superFuture, filteredFiles, mode); + d->m_indexingSupporter->refreshSourceFiles(filteredFiles, mode); + return d->m_internalIndexingSupport->refreshSourceFiles(filteredFiles, mode); } QList CppModelManager::projectInfos() const @@ -1078,25 +1070,23 @@ void CppModelManager::recalculateProjectPartMappings() d->m_symbolFinder.clearCache(); } -void CppModelManager::watchForCanceledProjectIndexer(const QVector> &futures, +void CppModelManager::watchForCanceledProjectIndexer(const QFuture &future, ProjectExplorer::Project *project) { - for (const QFuture &future : futures) { - if (future.isCanceled() || future.isFinished()) - continue; + if (future.isCanceled() || future.isFinished()) + return; - auto watcher = new QFutureWatcher(this); - connect(watcher, &QFutureWatcher::canceled, this, [this, project, watcher]() { - if (d->m_projectToIndexerCanceled.contains(project)) // Project not yet removed - d->m_projectToIndexerCanceled.insert(project, true); - watcher->deleteLater(); - }); - connect(watcher, &QFutureWatcher::finished, this, [this, project, watcher]() { - d->m_projectToIndexerCanceled.remove(project); - watcher->deleteLater(); - }); - watcher->setFuture(future); - } + auto watcher = new QFutureWatcher(this); + connect(watcher, &QFutureWatcher::canceled, this, [this, project, watcher]() { + if (d->m_projectToIndexerCanceled.contains(project)) // Project not yet removed + d->m_projectToIndexerCanceled.insert(project, true); + watcher->deleteLater(); + }); + connect(watcher, &QFutureWatcher::finished, this, [this, project, watcher]() { + d->m_projectToIndexerCanceled.remove(project); + watcher->deleteLater(); + }); + watcher->setFuture(future); } void CppModelManager::updateCppEditorDocuments(bool projectsUpdated) const @@ -1128,8 +1118,7 @@ void CppModelManager::updateCppEditorDocuments(bool projectsUpdated) const } } -QFuture CppModelManager::updateProjectInfo(QFutureInterface &futureInterface, - const ProjectInfo &newProjectInfo) +QFuture CppModelManager::updateProjectInfo(const ProjectInfo &newProjectInfo) { if (!newProjectInfo.isValid()) return QFuture(); @@ -1221,12 +1210,12 @@ QFuture CppModelManager::updateProjectInfo(QFutureInterface &futureI updateCppEditorDocuments(/*projectsUpdated = */ true); // Trigger reindexing - const QFuture indexingFuture = updateSourceFiles(futureInterface, filesToReindex, + const QFuture indexingFuture = updateSourceFiles(filesToReindex, ForcedProgressNotification); if (!filesToReindex.isEmpty()) { d->m_projectToIndexerCanceled.insert(project, false); } - watchForCanceledProjectIndexer({futureInterface.future(), indexingFuture}, project); + watchForCanceledProjectIndexer(indexingFuture, project); return indexingFuture; } diff --git a/src/plugins/cpptools/cppmodelmanager.h b/src/plugins/cpptools/cppmodelmanager.h index 4d44e58a0be..eeae9180c66 100644 --- a/src/plugins/cpptools/cppmodelmanager.h +++ b/src/plugins/cpptools/cppmodelmanager.h @@ -106,17 +106,13 @@ public: QFuture updateSourceFiles(const QSet &sourceFiles, ProgressNotificationMode mode = ReservedProgressNotification); - QFuture updateSourceFiles(const QFutureInterface &superFuture, - const QSet &sourceFiles, - ProgressNotificationMode mode = ReservedProgressNotification); void updateCppEditorDocuments(bool projectsUpdated = false) const; WorkingCopy workingCopy() const; QByteArray codeModelConfiguration() const; QList projectInfos() const; ProjectInfo projectInfo(ProjectExplorer::Project *project) const; - QFuture updateProjectInfo(QFutureInterface &futureInterface, - const ProjectInfo &newProjectInfo); + QFuture updateProjectInfo(const ProjectInfo &newProjectInfo); /// \return The project part with the given project file ProjectPart::Ptr projectPartForId(const QString &projectPartId) const override; @@ -274,7 +270,7 @@ private: void initializeBuiltinModelManagerSupport(); void delayedGC(); void recalculateProjectPartMappings(); - void watchForCanceledProjectIndexer(const QVector > &futures, + void watchForCanceledProjectIndexer(const QFuture &future, ProjectExplorer::Project *project); void replaceSnapshot(const CPlusPlus::Snapshot &newSnapshot); diff --git a/src/plugins/cpptools/cppmodelmanager_test.cpp b/src/plugins/cpptools/cppmodelmanager_test.cpp index 78de5f1583e..2b77700cb84 100644 --- a/src/plugins/cpptools/cppmodelmanager_test.cpp +++ b/src/plugins/cpptools/cppmodelmanager_test.cpp @@ -190,8 +190,7 @@ void CppToolsPlugin::test_modelmanager_paths_are_clean() {testDataDir.frameworksDir(false), HeaderPathType::Framework}}; pi.appendProjectPart(part); - QFutureInterface dummy; - mm->updateProjectInfo(dummy, pi); + mm->updateProjectInfo(pi); ProjectExplorer::HeaderPaths headerPaths = mm->headerPaths(); QCOMPARE(headerPaths.size(), 2); @@ -223,8 +222,7 @@ void CppToolsPlugin::test_modelmanager_framework_headers() part->files << ProjectFile(source, ProjectFile::CXXSource); pi.appendProjectPart(part); - QFutureInterface dummy; - mm->updateProjectInfo(dummy, pi).waitForFinished(); + mm->updateProjectInfo(pi).waitForFinished(); QCoreApplication::processEvents(); QVERIFY(mm->snapshot().contains(source)); @@ -323,8 +321,7 @@ void CppToolsPlugin::test_modelmanager_refresh_several_times() part->files.append(ProjectFile(testHeader2, ProjectFile::CXXHeader)); part->files.append(ProjectFile(testCpp, ProjectFile::CXXSource)); pi.appendProjectPart(part); - QFutureInterface dummy; - mm->updateProjectInfo(dummy, pi); + mm->updateProjectInfo(pi); CPlusPlus::Snapshot snapshot; QSet refreshedFiles; @@ -387,8 +384,7 @@ void CppToolsPlugin::test_modelmanager_refresh_test_for_changes() // Reindexing triggers a reparsing thread helper.resetRefreshedSourceFiles(); - QFutureInterface dummy; - QFuture firstFuture = mm->updateProjectInfo(dummy, pi); + QFuture firstFuture = mm->updateProjectInfo(pi); QVERIFY(firstFuture.isStarted() || firstFuture.isRunning()); firstFuture.waitForFinished(); const QSet refreshedFiles = helper.waitForRefreshedSourceFiles(); @@ -396,7 +392,7 @@ void CppToolsPlugin::test_modelmanager_refresh_test_for_changes() QVERIFY(refreshedFiles.contains(testCpp)); // No reindexing since nothing has changed - QFuture subsequentFuture = mm->updateProjectInfo(dummy, pi); + QFuture subsequentFuture = mm->updateProjectInfo(pi); QVERIFY(subsequentFuture.isCanceled() && subsequentFuture.isFinished()); } diff --git a/src/plugins/cpptools/cppprojectinfogenerator.cpp b/src/plugins/cpptools/cppprojectinfogenerator.cpp index b8b969c2d3d..f5da863a33c 100644 --- a/src/plugins/cpptools/cppprojectinfogenerator.cpp +++ b/src/plugins/cpptools/cppprojectinfogenerator.cpp @@ -42,9 +42,8 @@ using namespace ProjectExplorer; namespace CppTools { namespace Internal { -ProjectInfoGenerator::ProjectInfoGenerator( - const QFutureInterface &futureInterface, - const ProjectUpdateInfo &projectUpdateInfo) +ProjectInfoGenerator::ProjectInfoGenerator(const QFutureInterface &futureInterface, + const ProjectUpdateInfo &projectUpdateInfo) : m_futureInterface(futureInterface) , m_projectUpdateInfo(projectUpdateInfo) { diff --git a/src/plugins/cpptools/cppprojectinfogenerator.h b/src/plugins/cpptools/cppprojectinfogenerator.h index 9e484636be5..7e97f1c5ca2 100644 --- a/src/plugins/cpptools/cppprojectinfogenerator.h +++ b/src/plugins/cpptools/cppprojectinfogenerator.h @@ -36,7 +36,7 @@ namespace Internal { class ProjectInfoGenerator { public: - ProjectInfoGenerator(const QFutureInterface &futureInterface, + ProjectInfoGenerator(const QFutureInterface &futureInterface, const ProjectExplorer::ProjectUpdateInfo &projectUpdateInfo); ProjectInfo generate(); @@ -52,7 +52,7 @@ private: Utils::LanguageExtensions languageExtensions); private: - const QFutureInterface m_futureInterface; + const QFutureInterface m_futureInterface; const ProjectExplorer::ProjectUpdateInfo &m_projectUpdateInfo; bool m_cToolchainMissing = false; bool m_cxxToolchainMissing = false; diff --git a/src/plugins/cpptools/cppprojectupdater.cpp b/src/plugins/cpptools/cppprojectupdater.cpp index d17c2609302..f0b0bda0902 100644 --- a/src/plugins/cpptools/cppprojectupdater.cpp +++ b/src/plugins/cpptools/cppprojectupdater.cpp @@ -33,12 +33,16 @@ #include #include +#include + namespace CppTools { CppProjectUpdater::CppProjectUpdater() { - connect(&m_generateFutureWatcher, &QFutureWatcher::finished, - this, &CppProjectUpdater::onProjectInfoGenerated); + connect(&m_generateFutureWatcher, + &QFutureWatcher::finished, + this, + &CppProjectUpdater::onProjectInfoGenerated); } CppProjectUpdater::~CppProjectUpdater() @@ -50,7 +54,6 @@ void CppProjectUpdater::update(const ProjectExplorer::ProjectUpdateInfo &project { // Stop previous update. cancelAndWaitForFinished(); - m_futureInterface = QFutureInterface(); m_projectUpdateInfo = projectUpdateInfo; @@ -60,26 +63,30 @@ void CppProjectUpdater::update(const ProjectExplorer::ProjectUpdateInfo &project this, &CppProjectUpdater::onToolChainRemoved); // Run the project info generator in a worker thread and continue if that one is finished. - const QFuture future = Utils::runAsync([=]() { + m_generateFuture = Utils::runAsync([=](QFutureInterface &futureInterface) { ProjectUpdateInfo fullProjectUpdateInfo = projectUpdateInfo; if (fullProjectUpdateInfo.rppGenerator) fullProjectUpdateInfo.rawProjectParts = fullProjectUpdateInfo.rppGenerator(); - Internal::ProjectInfoGenerator generator(m_futureInterface, fullProjectUpdateInfo); - return generator.generate(); + Internal::ProjectInfoGenerator generator(futureInterface, fullProjectUpdateInfo); + futureInterface.reportResult(generator.generate()); }); - m_generateFutureWatcher.setFuture(future); + m_generateFutureWatcher.setFuture(m_generateFuture); } void CppProjectUpdater::cancel() { - disconnect(&m_generateFutureWatcher); - m_futureInterface.cancel(); + m_generateFutureWatcher.setFuture({}); + m_generateFuture.cancel(); + m_updateFuture.cancel(); } void CppProjectUpdater::cancelAndWaitForFinished() { cancel(); - m_futureInterface.waitForFinished(); + if (m_generateFuture.isRunning()) + m_generateFuture.waitForFinished(); + if (m_updateFuture.isRunning()) + m_updateFuture.waitForFinished(); } void CppProjectUpdater::onToolChainRemoved(ProjectExplorer::ToolChain *t) @@ -96,11 +103,11 @@ void CppProjectUpdater::onProjectInfoGenerated() disconnect(ToolChainManager::instance(), &ToolChainManager::toolChainRemoved, this, &CppProjectUpdater::onToolChainRemoved); - if (m_futureInterface.isCanceled()) + if (m_generateFutureWatcher.isCanceled() || m_generateFutureWatcher.future().resultCount() < 1) return; - QFuture future = CppModelManager::instance() - ->updateProjectInfo(m_futureInterface, m_generateFutureWatcher.result()); + m_updateFuture = CppModelManager::instance()->updateProjectInfo( + m_generateFutureWatcher.result()); } CppProjectUpdaterFactory::CppProjectUpdaterFactory() diff --git a/src/plugins/cpptools/cppprojectupdater.h b/src/plugins/cpptools/cppprojectupdater.h index 8167b071cf0..f3f85a8a14f 100644 --- a/src/plugins/cpptools/cppprojectupdater.h +++ b/src/plugins/cpptools/cppprojectupdater.h @@ -29,7 +29,6 @@ #include "cpptools_global.h" #include "projectinfo.h" -#include #include namespace CppTools { @@ -67,7 +66,8 @@ private: private: ProjectExplorer::ProjectUpdateInfo m_projectUpdateInfo; - QFutureInterface m_futureInterface; + QFuture m_generateFuture; + QFuture m_updateFuture; QFutureWatcher m_generateFutureWatcher; }; diff --git a/src/plugins/cpptools/insertionpointlocator.cpp b/src/plugins/cpptools/insertionpointlocator.cpp index e0063567948..228d5344306 100644 --- a/src/plugins/cpptools/insertionpointlocator.cpp +++ b/src/plugins/cpptools/insertionpointlocator.cpp @@ -32,6 +32,7 @@ #include +#include #include #include @@ -545,6 +546,16 @@ static InsertionLocation nextToSurroundingDefinitions(Symbol *declaration, return noResult; targetFile->cppDocument()->translationUnit()->getTokenStartPosition(functionDefinition->firstToken(), &line, &column); + const QList path = ASTPath(targetFile->cppDocument())(line, column); + for (auto it = path.rbegin(); it != path.rend(); ++it) { + if (const auto templateDecl = (*it)->asTemplateDeclaration()) { + if (templateDecl->declaration == functionDefinition) { + targetFile->cppDocument()->translationUnit()->getTokenStartPosition( + templateDecl->firstToken(), &line, &column); + } + break; + } + } } return InsertionLocation(QString::fromUtf8(definitionFunction->fileName()), prefix, suffix, line, column); diff --git a/src/plugins/cpptools/modelmanagertesthelper.cpp b/src/plugins/cpptools/modelmanagertesthelper.cpp index 3d5f5cbdc96..08d01c02e06 100644 --- a/src/plugins/cpptools/modelmanagertesthelper.cpp +++ b/src/plugins/cpptools/modelmanagertesthelper.cpp @@ -93,8 +93,7 @@ ModelManagerTestHelper::Project *ModelManagerTestHelper::createProject(const QSt QSet ModelManagerTestHelper::updateProjectInfo(const CppTools::ProjectInfo &projectInfo) { resetRefreshedSourceFiles(); - QFutureInterface dummy; - CppModelManager::instance()->updateProjectInfo(dummy, projectInfo).waitForFinished(); + CppModelManager::instance()->updateProjectInfo(projectInfo).waitForFinished(); QCoreApplication::processEvents(); return waitForRefreshedSourceFiles(); } diff --git a/src/plugins/debugger/debuggersourcepathmappingwidget.cpp b/src/plugins/debugger/debuggersourcepathmappingwidget.cpp index ef7b609b6be..2f6939c16cf 100644 --- a/src/plugins/debugger/debuggersourcepathmappingwidget.cpp +++ b/src/plugins/debugger/debuggersourcepathmappingwidget.cpp @@ -145,7 +145,8 @@ bool SourcePathMappingModel::isNewPlaceHolder(const Mapping &m) const // Return raw, unfixed mapping Mapping SourcePathMappingModel::rawMappingAt(int row) const { - return Mapping(item(row, SourceColumn)->text(), item(row, TargetColumn)->text()); + return Mapping(QDir::fromNativeSeparators(item(row, SourceColumn)->text()), + QDir::fromNativeSeparators(item(row, TargetColumn)->text())); } // Return mapping, empty if it is the place holder. diff --git a/src/plugins/help/helpmanager.cpp b/src/plugins/help/helpmanager.cpp index 2d588e502be..dff38b9af2c 100644 --- a/src/plugins/help/helpmanager.cpp +++ b/src/plugins/help/helpmanager.cpp @@ -36,7 +36,6 @@ #include #include #include -#include #include #include diff --git a/src/plugins/mesonprojectmanager/project/mesonprojectparser.h b/src/plugins/mesonprojectmanager/project/mesonprojectparser.h index 57805060f0a..2d5cd4d2703 100644 --- a/src/plugins/mesonprojectmanager/project/mesonprojectparser.h +++ b/src/plugins/mesonprojectmanager/project/mesonprojectparser.h @@ -40,7 +40,6 @@ #include #include -#include #include namespace MesonProjectManager { diff --git a/src/plugins/nim/project/nimproject.h b/src/plugins/nim/project/nimproject.h index 540d2129bba..62497770ed9 100644 --- a/src/plugins/nim/project/nimproject.h +++ b/src/plugins/nim/project/nimproject.h @@ -29,7 +29,6 @@ #include #include -#include #include namespace Nim { diff --git a/src/plugins/projectexplorer/extracompiler.cpp b/src/plugins/projectexplorer/extracompiler.cpp index 1a764712ca0..a0c5ab4ec32 100644 --- a/src/plugins/projectexplorer/extracompiler.cpp +++ b/src/plugins/projectexplorer/extracompiler.cpp @@ -42,6 +42,7 @@ #include #include +#include #include #include #include diff --git a/src/plugins/projectexplorer/extracompiler.h b/src/plugins/projectexplorer/extracompiler.h index 1ad6d806923..884c1bf6830 100644 --- a/src/plugins/projectexplorer/extracompiler.h +++ b/src/plugins/projectexplorer/extracompiler.h @@ -34,7 +34,6 @@ #include #include -#include #include #include @@ -43,6 +42,13 @@ QT_FORWARD_DECLARE_CLASS(QProcess); QT_FORWARD_DECLARE_CLASS(QThreadPool); +QT_BEGIN_NAMESPACE +template +class QFutureInterface; +template +class QFutureWatcher; +QT_END_NAMESPACE + namespace ProjectExplorer { diff --git a/src/plugins/projectexplorer/projectnodes.cpp b/src/plugins/projectexplorer/projectnodes.cpp index 86072b81235..93d8a412f58 100644 --- a/src/plugins/projectexplorer/projectnodes.cpp +++ b/src/plugins/projectexplorer/projectnodes.cpp @@ -382,10 +382,11 @@ FileType FileNode::fileType() const return m_fileType; } -static QList scanForFilesRecursively(const Utils::FilePath &directory, - const std::function factory, - QSet &visited, QFutureInterface> *future, +static QList scanForFilesRecursively(QFutureInterface> &future, double progressStart, double progressRange, + const Utils::FilePath &directory, + const std::function factory, + QSet &visited, const QList &versionControls) { QList result; @@ -403,7 +404,7 @@ static QList scanForFilesRecursively(const Utils::FilePath &director const double progressIncrement = progressRange / static_cast(entries.count()); int lastIntProgress = 0; for (const QFileInfo &entry : entries) { - if (future && future->isCanceled()) + if (future.isCanceled()) return result; const Utils::FilePath entryName = Utils::FilePath::fromString(entry.absoluteFilePath()); @@ -411,33 +412,29 @@ static QList scanForFilesRecursively(const Utils::FilePath &director return vc->isVcsFileOrDirectory(entryName); })) { if (entry.isDir()) - result.append(scanForFilesRecursively(entryName, factory, visited, future, progress, progressIncrement, versionControls)); + result.append(scanForFilesRecursively(future, progress, progressIncrement, entryName, factory, visited, versionControls)); else if (FileNode *node = factory(entryName)) result.append(node); } - if (future) { - progress += progressIncrement; - const int intProgress = std::min(static_cast(progressStart + progress), future->progressMaximum()); - if (lastIntProgress < intProgress) { - future->setProgressValue(intProgress); - lastIntProgress = intProgress; - } + progress += progressIncrement; + const int intProgress = std::min(static_cast(progressStart + progress), future.progressMaximum()); + if (lastIntProgress < intProgress) { + future.setProgressValue(intProgress); + lastIntProgress = intProgress; } } - if (future) - future->setProgressValue(std::min(static_cast(progressStart + progressRange), future->progressMaximum())); + future.setProgressValue(std::min(static_cast(progressStart + progressRange), future.progressMaximum())); return result; } QList -FileNode::scanForFiles(const Utils::FilePath &directory, - const std::function factory, - QFutureInterface> *future) +FileNode::scanForFiles(QFutureInterface> &future, + const Utils::FilePath &directory, + const std::function factory) { QSet visited; - if (future) - future->setProgressRange(0, 1000000); - return scanForFilesRecursively(directory, factory, visited, future, 0.0, 1000000.0, + future.setProgressRange(0, 1000000); + return scanForFilesRecursively(future, 0.0, 1000000.0, directory, factory, visited, Core::VcsManager::versionControls()); } diff --git a/src/plugins/projectexplorer/projectnodes.h b/src/plugins/projectexplorer/projectnodes.h index c5eea633749..0fd53414d1b 100644 --- a/src/plugins/projectexplorer/projectnodes.h +++ b/src/plugins/projectexplorer/projectnodes.h @@ -201,9 +201,9 @@ public: const FileNode *asFileNode() const final { return this; } static QList - scanForFiles(const Utils::FilePath &directory, - const std::function factory, - QFutureInterface> *future = nullptr); + scanForFiles(QFutureInterface> &future, + const Utils::FilePath &directory, + const std::function factory); bool supportsAction(ProjectAction action, const Node *node) const override; QString displayName() const override; diff --git a/src/plugins/projectexplorer/treescanner.cpp b/src/plugins/projectexplorer/treescanner.cpp index 14f10c66db1..870ec538179 100644 --- a/src/plugins/projectexplorer/treescanner.cpp +++ b/src/plugins/projectexplorer/treescanner.cpp @@ -64,12 +64,11 @@ bool TreeScanner::asyncScanForFiles(const Utils::FilePath &directory) if (!m_futureWatcher.isFinished()) return false; - auto fi = new FutureInterface(); - m_scanFuture = fi->future(); + m_scanFuture = Utils::runAsync([this, directory](FutureInterface &fi) { + TreeScanner::scanForFiles(fi, directory, m_filter, m_factory); + }); m_futureWatcher.setFuture(m_scanFuture); - Utils::runAsync([this, fi, directory]() { TreeScanner::scanForFiles(fi, directory, m_filter, m_factory); }); - return true; } @@ -145,14 +144,10 @@ FileType TreeScanner::genericFileType(const Utils::MimeType &mimeType, const Uti return Node::fileTypeForMimeType(mimeType); } -void TreeScanner::scanForFiles(FutureInterface *fi, const Utils::FilePath& directory, +void TreeScanner::scanForFiles(FutureInterface &fi, const Utils::FilePath& directory, const FileFilter &filter, const FileTypeFactory &factory) { - std::unique_ptr fip(fi); - fip->reportStarted(); - - Result nodes = FileNode::scanForFiles( - directory, + Result nodes = FileNode::scanForFiles(fi, directory, [&filter, &factory](const Utils::FilePath &fn) -> FileNode * { const Utils::MimeType mimeType = Utils::mimeTypeForFile(fn.toString()); @@ -166,13 +161,12 @@ void TreeScanner::scanForFiles(FutureInterface *fi, const Utils::FilePath& direc type = factory(mimeType, fn); return new FileNode(fn, type); - }, fip.get()); + }); Utils::sort(nodes, ProjectExplorer::Node::sortByPath); - fip->setProgressValue(fip->progressMaximum()); - fip->reportResult(nodes); - fip->reportFinished(); + fi.setProgressValue(fi.progressMaximum()); + fi.reportResult(nodes); } } // namespace ProjectExplorer diff --git a/src/plugins/projectexplorer/treescanner.h b/src/plugins/projectexplorer/treescanner.h index e2ad544bde0..28fe47ba5b2 100644 --- a/src/plugins/projectexplorer/treescanner.h +++ b/src/plugins/projectexplorer/treescanner.h @@ -87,7 +87,7 @@ signals: void finished(); private: - static void scanForFiles(FutureInterface *fi, const Utils::FilePath &directory, + static void scanForFiles(FutureInterface &fi, const Utils::FilePath &directory, const FileFilter &filter, const FileTypeFactory &factory); private: diff --git a/src/plugins/qmakeprojectmanager/qmakeproject.cpp b/src/plugins/qmakeprojectmanager/qmakeproject.cpp index 6a71cad30b7..28f003cd3f5 100644 --- a/src/plugins/qmakeprojectmanager/qmakeproject.cpp +++ b/src/plugins/qmakeprojectmanager/qmakeproject.cpp @@ -72,6 +72,7 @@ #include #include #include +#include #include #include diff --git a/src/plugins/qmakeprojectmanager/qmakeproject.h b/src/plugins/qmakeprojectmanager/qmakeproject.h index 93044db96b4..af10652c359 100644 --- a/src/plugins/qmakeprojectmanager/qmakeproject.h +++ b/src/plugins/qmakeprojectmanager/qmakeproject.h @@ -36,7 +36,6 @@ #include #include -#include QT_BEGIN_NAMESPACE class QMakeGlobals; diff --git a/src/plugins/qmldesigner/components/annotationeditor/annotationcommenttab.cpp b/src/plugins/qmldesigner/components/annotationeditor/annotationcommenttab.cpp index c7e1ab192c2..29e38362418 100644 --- a/src/plugins/qmldesigner/components/annotationeditor/annotationcommenttab.cpp +++ b/src/plugins/qmldesigner/components/annotationeditor/annotationcommenttab.cpp @@ -43,16 +43,16 @@ AnnotationCommentTab::AnnotationCommentTab(QWidget *parent) ui->titleEdit->setModel(new QStringListModel{QStringList{"Description", "Display Condition", - "helper_lines" - "highlight" + "helper lines", + "highlight", "project author", "project confirmed", "project developer", "project distributor", "project modified", - "project type" + "project type", "project version", - "Screen Description" + "Screen Description", "Section"}}); connect(ui->titleEdit, &QComboBox::currentTextChanged, diff --git a/src/plugins/qmldesigner/components/annotationeditor/annotationeditor.cpp b/src/plugins/qmldesigner/components/annotationeditor/annotationeditor.cpp index bfe248690c3..8085691354a 100644 --- a/src/plugins/qmldesigner/components/annotationeditor/annotationeditor.cpp +++ b/src/plugins/qmldesigner/components/annotationeditor/annotationeditor.cpp @@ -29,6 +29,10 @@ #include "annotation.h" #include "qmlmodelnodeproxy.h" + +#include +#include + #include #include @@ -175,6 +179,7 @@ void AnnotationEditor::removeFullAnnotation() void AnnotationEditor::acceptedClicked() { if (m_dialog) { + QmlDesignerPlugin::emitUsageStatistics(Constants::EVENT_ANNOTATION_ADDED); QString customId = m_dialog->customId(); Annotation annotation = m_dialog->annotation(); diff --git a/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp b/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp index dbad1d25530..0a8f567c54d 100644 --- a/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp +++ b/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp @@ -343,7 +343,7 @@ public: parentNode = selectionContext().currentSingleSelectedNode().parentProperty().parentModelNode(); if (!ModelNode::isThisOrAncestorLocked(parentNode)) { - ActionTemplate *selectionAction = new ActionTemplate(QString(), &ModelNodeOperations::select); + ActionTemplate *selectionAction = new ActionTemplate("SELECTION", {}, &ModelNodeOperations::select); selectionAction->setParent(menu()); selectionAction->setText(QString(QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Select parent: %1")).arg( captionForModelNode(parentNode))); @@ -363,7 +363,7 @@ public: && !ModelNode::isThisOrAncestorLocked(node)) { selectionContext().setTargetNode(node); QString what = QString(QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Select: %1")).arg(captionForModelNode(node)); - ActionTemplate *selectionAction = new ActionTemplate(what, &ModelNodeOperations::select); + ActionTemplate *selectionAction = new ActionTemplate("SELECT", what, &ModelNodeOperations::select); SelectionContext nodeSelectionContext = selectionContext(); nodeSelectionContext.setTargetNode(node); @@ -546,7 +546,7 @@ public: for (const QmlFlowItemNode &node : QmlFlowViewNode(selectionContext().rootNode()).flowItems()) { if (node != selectionContext().currentSingleSelectedNode().parentProperty().parentModelNode()) { QString what = QString(QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Connect: %1")).arg(captionForModelNode(node)); - ActionTemplate *connectionAction = new ActionTemplate(what, &ModelNodeOperations::addTransition); + ActionTemplate *connectionAction = new ActionTemplate("CONNECT", what, &ModelNodeOperations::addTransition); SelectionContext nodeSelectionContext = selectionContext(); nodeSelectionContext.setTargetNode(node); diff --git a/src/plugins/qmldesigner/components/componentcore/modelnodecontextmenu_helper.h b/src/plugins/qmldesigner/components/componentcore/modelnodecontextmenu_helper.h index 59029400e5a..7fe891fd726 100644 --- a/src/plugins/qmldesigner/components/componentcore/modelnodecontextmenu_helper.h +++ b/src/plugins/qmldesigner/components/componentcore/modelnodecontextmenu_helper.h @@ -29,6 +29,7 @@ #include "abstractaction.h" #include "abstractactiongroup.h" #include "qmlitemnode.h" +#include #include @@ -103,17 +104,19 @@ class ActionTemplate : public DefaultAction { public: - ActionTemplate(const QString &description, SelectionContextOperation action) - : DefaultAction(description), m_action(action) + ActionTemplate(const QByteArray &id, const QString &description, SelectionContextOperation action) + : DefaultAction(description), m_action(action), m_id(id) { } void actionTriggered(bool b) override { + QmlDesignerPlugin::emitUsageStatisticsContextAction(QString::fromUtf8(m_id)); m_selectionContext.setToggled(b); m_action(m_selectionContext); } SelectionContextOperation m_action; + QByteArray m_id; }; class ActionGroup : public AbstractActionGroup @@ -202,7 +205,7 @@ public: SelectionContextOperation selectionAction, SelectionContextPredicate enabled = &SelectionContextFunctors::always, SelectionContextPredicate visibility = &SelectionContextFunctors::always) : - AbstractAction(new ActionTemplate(description, selectionAction)), + AbstractAction(new ActionTemplate(id, description, selectionAction)), m_id(id), m_category(category), m_priority(priority), diff --git a/src/plugins/qmldesigner/components/integration/designdocument.cpp b/src/plugins/qmldesigner/components/integration/designdocument.cpp index 7f83f652e75..bedea2314f5 100644 --- a/src/plugins/qmldesigner/components/integration/designdocument.cpp +++ b/src/plugins/qmldesigner/components/integration/designdocument.cpp @@ -491,7 +491,7 @@ void DesignDocument::paste() if (rootNode.type() == "empty") return; - if (rootNode.id() == "designer__Selection") { // pasting multiple objects + if (rootNode.id() == "__multi__selection__") { // pasting multiple objects currentModel()->attachView(&view); ModelNode targetNode; @@ -545,7 +545,7 @@ void DesignDocument::paste() }); } else { // pasting single object - rewriterView()->executeInTransaction("DesignDocument::paste1", [this, &view, selectedNodes, rootNode]() { + rewriterView()->executeInTransaction("DesignDocument::paste1", [this, &view, rootNode]() { currentModel()->attachView(&view); ModelNode pastedNode(view.insertModel(rootNode)); ModelNode targetNode; diff --git a/src/plugins/qmldesigner/components/integration/designdocumentview.cpp b/src/plugins/qmldesigner/components/integration/designdocumentview.cpp index 336fbd8439c..25b468fe23a 100644 --- a/src/plugins/qmldesigner/components/integration/designdocumentview.cpp +++ b/src/plugins/qmldesigner/components/integration/designdocumentview.cpp @@ -141,23 +141,23 @@ void DesignDocumentView::fromText(const QString &text) inputModel->setFileUrl(model()->fileUrl()); QPlainTextEdit textEdit; QString imports; - foreach (const Import &import, model()->imports()) - imports += QStringLiteral("import ") + import.toString(true) + QLatin1Char(';') + QLatin1Char('\n'); + const auto modelImports = model()->imports(); + for (const Import &import : modelImports) + imports += "import " + import.toString(true) + QLatin1Char(';') + QLatin1Char('\n'); textEdit.setPlainText(imports + text); NotIndentingTextEditModifier modifier(&textEdit); - QScopedPointer rewriterView(new RewriterView(RewriterView::Amend, nullptr)); - rewriterView->setCheckSemanticErrors(false); - rewriterView->setTextModifier(&modifier); - inputModel->setRewriterView(rewriterView.data()); + RewriterView rewriterView; + rewriterView.setCheckSemanticErrors(false); + rewriterView.setTextModifier(&modifier); + inputModel->setRewriterView(&rewriterView); - rewriterView->restoreAuxiliaryData(); + rewriterView.restoreAuxiliaryData(); - if (rewriterView->errors().isEmpty() && rewriterView->rootModelNode().isValid()) { - ModelMerger merger(this); + if (rewriterView.errors().isEmpty() && rewriterView.rootModelNode().isValid()) { try { - merger.replaceModel(rewriterView->rootModelNode()); + replaceModel(rewriterView.rootModelNode()); } catch(Exception &/*e*/) { /* e.showException(); Do not show any error if the clipboard contains invalid QML */ } @@ -237,13 +237,13 @@ void DesignDocumentView::copyModelNodes(const QList &nodesToCopy) Q_ASSERT(view.rootModelNode().type() != "empty"); view.toClipboard(); - } else { //multi items selected + } else { // multi items selected foreach (ModelNode node, view.rootModelNode().directSubModelNodes()) { node.destroy(); } view.changeRootNodeType("QtQuick.Rectangle", 2, 0); - view.rootModelNode().setIdWithRefactoring("designer__Selection"); + view.rootModelNode().setIdWithRefactoring("__multi__selection__"); foreach (const ModelNode &selectedNode, selectedNodes) { ModelNode newNode(view.insertModel(selectedNode)); diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp index 10a253f5b6e..ae3569ff022 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp @@ -572,6 +572,7 @@ void ItemLibraryWidget::addResources() for (const AddResourceHandler &handler : handlers) { QStringList fileNames = partitionedFileNames.values(category); if (handler.category == category) { + QmlDesignerPlugin::emitUsageStatistics(Constants::EVENT_RESOURCE_IMPORTED + category); if (!handler.operation(fileNames, document->fileName().parentDir().toString())) Core::AsynchronousMessageBox::warning(tr("Failed to Add Files"), tr("Could not add %1 to project.").arg(fileNames.join(" "))); break; diff --git a/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp b/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp index 46bbfadb247..afd4af7e492 100644 --- a/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp +++ b/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp @@ -793,6 +793,11 @@ void NavigatorTreeModel::handleItemLibraryImageDrop(const QMimeData *mimeData, i } } +TypeName propertyType(const NodeAbstractProperty &property) +{ + return property.parentModelNode().metaInfo().propertyTypeName(property.name()); +} + void NavigatorTreeModel::moveNodesInteractive(NodeAbstractProperty &parentProperty, const QList &modelNodes, int targetIndex, @@ -801,7 +806,7 @@ void NavigatorTreeModel::moveNodesInteractive(NodeAbstractProperty &parentProper QTC_ASSERT(m_view, return); auto doMoveNodesInteractive = [&parentProperty, modelNodes, targetIndex](){ - const TypeName propertyQmlType = parentProperty.parentModelNode().metaInfo().propertyTypeName(parentProperty.name()); + const TypeName propertyQmlType = propertyType(parentProperty); int idx = targetIndex; for (const ModelNode &modelNode : modelNodes) { if (modelNode.isValid() diff --git a/src/plugins/qmldesigner/components/stateseditor/stateseditorview.cpp b/src/plugins/qmldesigner/components/stateseditor/stateseditorview.cpp index b777fbf4c25..eb4acb358d3 100644 --- a/src/plugins/qmldesigner/components/stateseditor/stateseditorview.cpp +++ b/src/plugins/qmldesigner/components/stateseditor/stateseditorview.cpp @@ -40,6 +40,8 @@ #include #include +#include +#include #include #include #include @@ -182,6 +184,8 @@ void StatesEditorView::addState() if (!QmlVisualNode::isValidQmlVisualNode(rootModelNode())) return; + QmlDesignerPlugin::emitUsageStatistics(Constants::EVENT_STATE_ADDED); + QStringList modelStateNames = rootStateGroup().names(); QString newStateName; @@ -192,17 +196,12 @@ void StatesEditorView::addState() break; } - try { + executeInTransaction("addState", [this, newStateName]() { rootModelNode().validId(); - if ((rootStateGroup().allStates().count() < 1) && //QtQuick import might be missing - (!model()->hasImport(Import::createLibraryImport("QtQuick", "1.0"), true, true))) { - model()->changeImports({Import::createLibraryImport("QtQuick", "1.0")}, {}); - } + ModelNode newState = rootStateGroup().addState(newStateName); setCurrentState(newState); - } catch (const RewritingException &e) { - e.showException(); - } + }); } void StatesEditorView::resetModel() @@ -236,9 +235,12 @@ void StatesEditorView::duplicateCurrentState() QStringList stateNames = rootStateGroup().names(); while (stateNames.contains(newName + QString::number(i))) i++; + const QString newStateName = newName + QString::number(i); - QmlModelState newState = state.duplicate(newName + QString::number(i)); - setCurrentState(newState); + executeInTransaction("addState", [this, newStateName, state]() { + QmlModelState newState = state.duplicate(newStateName); + setCurrentState(newState); + }); } void StatesEditorView::checkForStatesAvailability() @@ -303,7 +305,7 @@ void StatesEditorView::renameState(int internalNodeId, const QString &newName) setCurrentState(oldState); } - } catch (const RewritingException &e) { + } catch (const RewritingException &e) { e.showException(); } } diff --git a/src/plugins/qmldesigner/components/timelineeditor/timelineview.cpp b/src/plugins/qmldesigner/components/timelineeditor/timelineview.cpp index dab580a1469..9f87a33c002 100644 --- a/src/plugins/qmldesigner/components/timelineeditor/timelineview.cpp +++ b/src/plugins/qmldesigner/components/timelineeditor/timelineview.cpp @@ -44,6 +44,7 @@ #include #include #include +#include #include #include #include @@ -304,6 +305,8 @@ const QmlTimeline TimelineView::addNewTimeline() QTC_ASSERT(isAttached(), return QmlTimeline()); + QmlDesignerPlugin::emitUsageStatistics(Constants::EVENT_TIMELINE_ADDED); + try { ensureQtQuickTimelineImport(); } catch (const Exception &e) { diff --git a/src/plugins/qmldesigner/components/transitioneditor/transitioneditorview.cpp b/src/plugins/qmldesigner/components/transitioneditor/transitioneditorview.cpp index 10b95f59df5..62fb34403ba 100644 --- a/src/plugins/qmldesigner/components/transitioneditor/transitioneditorview.cpp +++ b/src/plugins/qmldesigner/components/transitioneditor/transitioneditorview.cpp @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -203,6 +204,8 @@ ModelNode TransitionEditorView::addNewTransition() states = QmlVisualNode(root).states().allStates(); } + QmlDesignerPlugin::emitUsageStatistics(Constants::EVENT_TRANSITION_ADDED); + if (states.isEmpty()) { Core::AsynchronousMessageBox::warning(tr("No States Defined"), tr("There are no states defined in this component.")); diff --git a/src/plugins/qmldesigner/designercore/imagecache/imagecache.cpp b/src/plugins/qmldesigner/designercore/imagecache/imagecache.cpp index 20409eb7fa2..e4eec4deacd 100644 --- a/src/plugins/qmldesigner/designercore/imagecache/imagecache.cpp +++ b/src/plugins/qmldesigner/designercore/imagecache/imagecache.cpp @@ -44,6 +44,7 @@ ImageCache::ImageCache(ImageCacheStorageInterface &storage, while (isRunning()) { if (auto [hasEntry, entry] = getEntry(); hasEntry) { request(entry.name, + entry.state, entry.requestType, std::move(entry.captureCallback), std::move(entry.abortCallback), @@ -60,13 +61,11 @@ ImageCache::ImageCache(ImageCacheStorageInterface &storage, ImageCache::~ImageCache() { clean(); - stopThread(); - m_condition.notify_all(); - if (m_backgroundThread.joinable()) - m_backgroundThread.join(); + wait(); } void ImageCache::request(Utils::SmallStringView name, + Utils::SmallStringView state, ImageCache::RequestType requestType, ImageCache::CaptureCallback captureCallback, ImageCache::AbortCallback abortCallback, @@ -74,9 +73,11 @@ void ImageCache::request(Utils::SmallStringView name, ImageCacheGeneratorInterface &generator, TimeStampProviderInterface &timeStampProvider) { + const auto id = state.empty() ? Utils::PathString{name} : Utils::PathString{name, "+", state}; + const auto timeStamp = timeStampProvider.timeStamp(name); - const auto entry = requestType == RequestType::Image ? storage.fetchImage(name, timeStamp) - : storage.fetchIcon(name, timeStamp); + const auto entry = requestType == RequestType::Image ? storage.fetchImage(id, timeStamp) + : storage.fetchIcon(id, timeStamp); if (entry.hasEntry) { if (entry.image.isNull()) @@ -84,23 +85,45 @@ void ImageCache::request(Utils::SmallStringView name, else captureCallback(entry.image); } else { - generator.generateImage(name, timeStamp, std::move(captureCallback), std::move(abortCallback)); + generator.generateImage(name, + state, + timeStamp, + std::move(captureCallback), + std::move(abortCallback)); } } +void ImageCache::wait() +{ + stopThread(); + m_condition.notify_all(); + if (m_backgroundThread.joinable()) + m_backgroundThread.join(); +} + void ImageCache::requestImage(Utils::PathString name, ImageCache::CaptureCallback captureCallback, - AbortCallback abortCallback) + AbortCallback abortCallback, + Utils::SmallString state) { - addEntry(std::move(name), std::move(captureCallback), std::move(abortCallback), RequestType::Image); + addEntry(std::move(name), + std::move(state), + std::move(captureCallback), + std::move(abortCallback), + RequestType::Image); m_condition.notify_all(); } void ImageCache::requestIcon(Utils::PathString name, ImageCache::CaptureCallback captureCallback, - ImageCache::AbortCallback abortCallback) + ImageCache::AbortCallback abortCallback, + Utils::SmallString state) { - addEntry(std::move(name), std::move(captureCallback), std::move(abortCallback), RequestType::Icon); + addEntry(std::move(name), + std::move(state), + std::move(captureCallback), + std::move(abortCallback), + RequestType::Icon); m_condition.notify_all(); } @@ -110,6 +133,13 @@ void ImageCache::clean() m_generator.clean(); } +void ImageCache::waitForFinished() +{ + wait(); + + m_generator.waitForFinished(); +} + std::tuple ImageCache::getEntry() { std::unique_lock lock{m_mutex}; @@ -124,6 +154,7 @@ std::tuple ImageCache::getEntry() } void ImageCache::addEntry(Utils::PathString &&name, + Utils::SmallString &&state, ImageCache::CaptureCallback &&captureCallback, AbortCallback &&abortCallback, RequestType requestType) @@ -131,6 +162,7 @@ void ImageCache::addEntry(Utils::PathString &&name, std::unique_lock lock{m_mutex}; m_entries.emplace_back(std::move(name), + std::move(state), std::move(captureCallback), std::move(abortCallback), requestType); @@ -160,7 +192,7 @@ void ImageCache::stopThread() bool ImageCache::isRunning() { std::unique_lock lock{m_mutex}; - return !m_finishing; + return !m_finishing || m_entries.size(); } } // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/designercore/imagecache/imagecachecollector.cpp b/src/plugins/qmldesigner/designercore/imagecache/imagecachecollector.cpp index 1bb7262d17a..55d44d7d49f 100644 --- a/src/plugins/qmldesigner/designercore/imagecache/imagecachecollector.cpp +++ b/src/plugins/qmldesigner/designercore/imagecache/imagecachecollector.cpp @@ -67,6 +67,7 @@ ImageCacheCollector::ImageCacheCollector(ImageCacheConnectionManager &connection ImageCacheCollector::~ImageCacheCollector() = default; void ImageCacheCollector::start(Utils::SmallStringView name, + Utils::SmallStringView state, CaptureCallback captureCallback, AbortCallback abortCallback) { @@ -91,6 +92,11 @@ void ImageCacheCollector::start(Utils::SmallStringView name, return; } + ModelNode stateNode = rewriterView.modelNodeForId(QString{state}); + + if (stateNode.isValid()) + rewriterView.setCurrentStateNode(stateNode); + m_connectionManager.setCallback(std::move(captureCallback)); nodeInstanceView.setTarget(m_target.get()); diff --git a/src/plugins/qmldesigner/designercore/imagecache/imagecachecollector.h b/src/plugins/qmldesigner/designercore/imagecache/imagecachecollector.h index e39f95f5732..d7f19e17a7c 100644 --- a/src/plugins/qmldesigner/designercore/imagecache/imagecachecollector.h +++ b/src/plugins/qmldesigner/designercore/imagecache/imagecachecollector.h @@ -53,6 +53,7 @@ public: ~ImageCacheCollector(); void start(Utils::SmallStringView filePath, + Utils::SmallStringView state, CaptureCallback captureCallback, AbortCallback abortCallback) override; diff --git a/src/plugins/qmldesigner/designercore/imagecache/imagecachecollectorinterface.h b/src/plugins/qmldesigner/designercore/imagecache/imagecachecollectorinterface.h index e6528f2ec37..4540d8e0a19 100644 --- a/src/plugins/qmldesigner/designercore/imagecache/imagecachecollectorinterface.h +++ b/src/plugins/qmldesigner/designercore/imagecache/imagecachecollectorinterface.h @@ -38,6 +38,7 @@ public: using AbortCallback = std::function; virtual void start(Utils::SmallStringView filePath, + Utils::SmallStringView state, CaptureCallback captureCallback, AbortCallback abortCallback) = 0; diff --git a/src/plugins/qmldesigner/designercore/imagecache/imagecachegenerator.cpp b/src/plugins/qmldesigner/designercore/imagecache/imagecachegenerator.cpp index 5b8f737515a..0ae7aab813d 100644 --- a/src/plugins/qmldesigner/designercore/imagecache/imagecachegenerator.cpp +++ b/src/plugins/qmldesigner/designercore/imagecache/imagecachegenerator.cpp @@ -44,21 +44,23 @@ ImageCacheGenerator::ImageCacheGenerator(ImageCacheCollectorInterface &collector ImageCacheGenerator::~ImageCacheGenerator() { clean(); - stopThread(); - m_condition.notify_all(); - - if (m_backgroundThread) - m_backgroundThread->wait(); + waitForFinished(); } -void ImageCacheGenerator::generateImage(Utils::SmallStringView name, - Sqlite::TimeStamp timeStamp, - ImageCacheGeneratorInterface::CaptureCallback &&captureCallback, - AbortCallback &&abortCallback) +void ImageCacheGenerator::generateImage( + Utils::SmallStringView name, + Utils::SmallStringView state, + Sqlite::TimeStamp timeStamp, + ImageCacheGeneratorInterface::CaptureCallback &&captureCallback, + AbortCallback &&abortCallback) { { std::lock_guard lock{m_mutex}; - m_tasks.emplace_back(name, timeStamp, std::move(captureCallback), std::move(abortCallback)); + m_tasks.emplace_back(name, + state, + timeStamp, + std::move(captureCallback), + std::move(abortCallback)); } m_condition.notify_all(); @@ -72,6 +74,15 @@ void ImageCacheGenerator::clean() m_tasks.clear(); } +void ImageCacheGenerator::waitForFinished() +{ + stopThread(); + m_condition.notify_all(); + + if (m_backgroundThread) + m_backgroundThread->wait(); +} + void ImageCacheGenerator::startGeneration() { while (isRunning()) { @@ -82,7 +93,7 @@ void ImageCacheGenerator::startGeneration() { std::lock_guard lock{m_mutex}; - if (m_finishing) { + if (m_finishing && m_tasks.empty()) { m_storage.walCheckpointFull(); return; } @@ -94,6 +105,7 @@ void ImageCacheGenerator::startGeneration() m_collector.start( task.filePath, + task.state, [this, task](QImage &&image) { if (image.isNull()) task.abortCallback(); @@ -129,7 +141,7 @@ void ImageCacheGenerator::stopThread() bool ImageCacheGenerator::isRunning() { std::unique_lock lock{m_mutex}; - return !m_finishing; + return !m_finishing || m_tasks.size(); } } // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/designercore/imagecache/imagecachegenerator.h b/src/plugins/qmldesigner/designercore/imagecache/imagecachegenerator.h index 945d53eabe5..839cb61c5fe 100644 --- a/src/plugins/qmldesigner/designercore/imagecache/imagecachegenerator.h +++ b/src/plugins/qmldesigner/designercore/imagecache/imagecachegenerator.h @@ -51,26 +51,32 @@ public: ~ImageCacheGenerator(); void generateImage(Utils::SmallStringView filePath, + Utils::SmallStringView state, Sqlite::TimeStamp timeStamp, CaptureCallback &&captureCallback, AbortCallback &&abortCallback) override; void clean() override; + void waitForFinished() override; + private: struct Task { Task() = default; Task(Utils::SmallStringView filePath, + Utils::SmallStringView state, Sqlite::TimeStamp timeStamp, CaptureCallback &&captureCallback, AbortCallback &&abortCallback) : filePath(filePath) + , state(std::move(state)) , captureCallback(std::move(captureCallback)) , abortCallback(std::move(abortCallback)) , timeStamp(timeStamp) {} Utils::PathString filePath; + Utils::SmallString state; CaptureCallback captureCallback; AbortCallback abortCallback; Sqlite::TimeStamp timeStamp; diff --git a/src/plugins/qmldesigner/designercore/imagecache/imagecachegeneratorinterface.h b/src/plugins/qmldesigner/designercore/imagecache/imagecachegeneratorinterface.h index 26b96219951..07dd61bef61 100644 --- a/src/plugins/qmldesigner/designercore/imagecache/imagecachegeneratorinterface.h +++ b/src/plugins/qmldesigner/designercore/imagecache/imagecachegeneratorinterface.h @@ -39,12 +39,14 @@ public: using AbortCallback = std::function; virtual void generateImage(Utils::SmallStringView name, + Utils::SmallStringView state, Sqlite::TimeStamp timeStamp, CaptureCallback &&captureCallback, AbortCallback &&abortCallback) = 0; virtual void clean() = 0; + virtual void waitForFinished() = 0; protected: ~ImageCacheGeneratorInterface() = default; diff --git a/src/plugins/qmldesigner/designercore/include/imagecache.h b/src/plugins/qmldesigner/designercore/include/imagecache.h index 4ac360c2a50..f044dbd5d5d 100644 --- a/src/plugins/qmldesigner/designercore/include/imagecache.h +++ b/src/plugins/qmldesigner/designercore/include/imagecache.h @@ -54,12 +54,15 @@ public: void requestImage(Utils::PathString name, CaptureCallback captureCallback, - AbortCallback abortCallback); + AbortCallback abortCallback, + Utils::SmallString state = {}); void requestIcon(Utils::PathString name, CaptureCallback captureCallback, - AbortCallback abortCallback); + AbortCallback abortCallback, + Utils::SmallString state = {}); void clean(); + void waitForFinished(); private: enum class RequestType { Image, Icon }; @@ -67,16 +70,19 @@ private: { Entry() = default; Entry(Utils::PathString name, + Utils::SmallString state, CaptureCallback &&captureCallback, AbortCallback &&abortCallback, RequestType requestType) : name{std::move(name)} + , state{std::move(state)} , captureCallback{std::move(captureCallback)} , abortCallback{std::move(abortCallback)} , requestType{requestType} {} Utils::PathString name; + Utils::SmallString state; CaptureCallback captureCallback; AbortCallback abortCallback; RequestType requestType = RequestType::Image; @@ -84,6 +90,7 @@ private: std::tuple getEntry(); void addEntry(Utils::PathString &&name, + Utils::SmallString &&state, CaptureCallback &&captureCallback, AbortCallback &&abortCallback, RequestType requestType); @@ -92,6 +99,7 @@ private: void stopThread(); bool isRunning(); static void request(Utils::SmallStringView name, + Utils::SmallStringView state, ImageCache::RequestType requestType, ImageCache::CaptureCallback captureCallback, ImageCache::AbortCallback abortCallback, @@ -99,6 +107,9 @@ private: ImageCacheGeneratorInterface &generator, TimeStampProviderInterface &timeStampProvider); +private: + void wait(); + private: std::vector m_entries; mutable std::mutex m_mutex; diff --git a/src/plugins/qmldesigner/designercore/include/rewriterview.h b/src/plugins/qmldesigner/designercore/include/rewriterview.h index 5eae2f221fa..9ecc5d7b988 100644 --- a/src/plugins/qmldesigner/designercore/include/rewriterview.h +++ b/src/plugins/qmldesigner/designercore/include/rewriterview.h @@ -75,7 +75,7 @@ public: }; public: - RewriterView(DifferenceHandling differenceHandling, QObject *parent); + RewriterView(DifferenceHandling differenceHandling = RewriterView::Amend, QObject *parent = nullptr); ~RewriterView() override; void modelAttached(Model *model) override; diff --git a/src/plugins/qmldesigner/designercore/instances/nodeinstance.cpp b/src/plugins/qmldesigner/designercore/instances/nodeinstance.cpp index b74179fdef8..91bb2c30711 100644 --- a/src/plugins/qmldesigner/designercore/instances/nodeinstance.cpp +++ b/src/plugins/qmldesigner/designercore/instances/nodeinstance.cpp @@ -473,9 +473,7 @@ QPixmap NodeInstance::blurredRenderPixmap() const void NodeInstance::setRenderPixmap(const QImage &image) { d->renderPixmap = QPixmap::fromImage(image); -#ifndef QMLDESIGNER_TEST - d->renderPixmap.setDevicePixelRatio(QmlDesignerPlugin::formEditorDevicePixelRatio()); -#endif + d->blurredRenderPixmap = QPixmap(); } diff --git a/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp b/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp index 9f965a453c5..be7460827d0 100644 --- a/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp +++ b/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp @@ -856,7 +856,7 @@ CreateSceneCommand NodeInstanceView::createCreateSceneCommand() QList nodeList = allModelNodes(); QList instanceList; - foreach (const ModelNode &node, nodeList) { + for (const ModelNode &node : std::as_const(nodeList)) { NodeInstance instance = loadNode(node); if (!isSkippedNode(node)) instanceList.append(instance); @@ -868,7 +868,7 @@ CreateSceneCommand NodeInstanceView::createCreateSceneCommand() QList bindingPropertyList; QVector auxiliaryContainerVector; - foreach (const ModelNode &node, nodeList) { + for (const ModelNode &node : std::as_const(nodeList)) { variantPropertyList.append(node.variantProperties()); bindingPropertyList.append(node.bindingProperties()); if (node.isValid() && hasInstanceForModelNode(node)) { @@ -883,9 +883,8 @@ CreateSceneCommand NodeInstanceView::createCreateSceneCommand() } } - QVector instanceContainerList; - foreach (const NodeInstance &instance, instanceList) { + for (const NodeInstance &instance : std::as_const(instanceList)) { InstanceContainer::NodeSourceType nodeSourceType = static_cast(instance.modelNode().nodeSourceType()); InstanceContainer::NodeMetaType nodeMetaType = InstanceContainer::ObjectMetaType; @@ -911,7 +910,7 @@ CreateSceneCommand NodeInstanceView::createCreateSceneCommand() } QVector reparentContainerList; - foreach (const NodeInstance &instance, instanceList) { + for (const NodeInstance &instance : std::as_const(instanceList)) { if (instance.modelNode().hasParentProperty()) { NodeAbstractProperty parentProperty = instance.modelNode().parentProperty(); ReparentContainer container(instance.instanceId(), -1, PropertyName(), instanceForModelNode(parentProperty.parentModelNode()).instanceId(), parentProperty.name()); @@ -920,7 +919,7 @@ CreateSceneCommand NodeInstanceView::createCreateSceneCommand() } QVector idContainerList; - foreach (const NodeInstance &instance, instanceList) { + for (const NodeInstance &instance : std::as_const(instanceList)) { QString id = instance.modelNode().id(); if (!id.isEmpty()) { IdContainer container(instance.instanceId(), id); @@ -929,7 +928,7 @@ CreateSceneCommand NodeInstanceView::createCreateSceneCommand() } QVector valueContainerList; - foreach (const VariantProperty &property, variantPropertyList) { + for (const VariantProperty &property : std::as_const(variantPropertyList)) { ModelNode node = property.parentModelNode(); if (node.isValid() && hasInstanceForModelNode(node)) { NodeInstance instance = instanceForModelNode(node); @@ -939,7 +938,7 @@ CreateSceneCommand NodeInstanceView::createCreateSceneCommand() } QVector bindingContainerList; - foreach (const BindingProperty &property, bindingPropertyList) { + for (const BindingProperty &property : std::as_const(bindingPropertyList)) { ModelNode node = property.parentModelNode(); if (node.isValid() && hasInstanceForModelNode(node)) { NodeInstance instance = instanceForModelNode(node); @@ -949,7 +948,7 @@ CreateSceneCommand NodeInstanceView::createCreateSceneCommand() } QVector importVector; - foreach (const Import &import, model()->imports()) + for (const Import &import : model()->imports()) importVector.append(AddImportContainer(import.url(), import.file(), import.version(), import.alias(), import.importPaths())); QVector mockupTypesVector; @@ -993,19 +992,23 @@ CreateSceneCommand NodeInstanceView::createCreateSceneCommand() if (auto multiLanguageAspect = QmlProjectManager::QmlMultiLanguageAspect::current(m_currentTarget)) lastUsedLanguage = multiLanguageAspect->currentLocale(); - return CreateSceneCommand( - instanceContainerList, - reparentContainerList, - idContainerList, - valueContainerList, - bindingContainerList, - auxiliaryContainerVector, - importVector, - mockupTypesVector, - model()->fileUrl(), - m_edit3DToolStates[model()->fileUrl()], - lastUsedLanguage - ); + ModelNode stateNode = currentStateNode(); + qint32 stateInstanceId = 0; + if (stateNode.isValid() && stateNode.metaInfo().isSubclassOf("QtQuick.State", 1, 0)) + stateInstanceId = stateNode.internalId(); + + return CreateSceneCommand(instanceContainerList, + reparentContainerList, + idContainerList, + valueContainerList, + bindingContainerList, + auxiliaryContainerVector, + importVector, + mockupTypesVector, + model()->fileUrl(), + m_edit3DToolStates[model()->fileUrl()], + lastUsedLanguage, + stateInstanceId); } ClearSceneCommand NodeInstanceView::createClearSceneCommand() const diff --git a/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp b/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp index e6a61800e67..3fe1f396b28 100644 --- a/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp +++ b/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp @@ -1062,6 +1062,14 @@ static QByteArray getPackage(const QByteArray &name) return nameComponents.join('.'); } + +QList qtObjectTypes() +{ + static QList typeNames = {"QML.QtObject", "QtQml.QtObject", ".QObject"}; + + return typeNames; +} + bool NodeMetaInfoPrivate::cleverCheckType(const TypeName &otherType) const { if (otherType == qualfiedTypeName()) @@ -1070,6 +1078,9 @@ bool NodeMetaInfoPrivate::cleverCheckType(const TypeName &otherType) const if (isFileComponent()) return false; + if (qtObjectTypes().contains(qualfiedTypeName()) && qtObjectTypes().contains(otherType)) + return true; + const QByteArray typeName = getUnqualifiedName(otherType); const QByteArray package = getPackage(otherType); diff --git a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp index 708d120ba53..4684ca087f6 100644 --- a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp +++ b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp @@ -1025,7 +1025,11 @@ bool TextToModelMerger::load(const QString &data, DifferenceHandler &differenceH collectLinkErrors(&errors, ctxt); setupImports(m_document, differenceHandler); - setupPossibleImports(snapshot, m_vContext); + + if (!justSanityCheck) + setupPossibleImports(snapshot, m_vContext); + + qCInfo(rewriterBenchmark) << "imports setup:" << time.elapsed(); collectImportErrors(&errors); diff --git a/src/plugins/qmldesigner/qmldesignerconstants.h b/src/plugins/qmldesigner/qmldesignerconstants.h index c32f5b62ecf..1e7fea711bb 100644 --- a/src/plugins/qmldesigner/qmldesignerconstants.h +++ b/src/plugins/qmldesigner/qmldesignerconstants.h @@ -77,6 +77,13 @@ const char M_VIEW_WORKSPACES[] = "QmlDesigner.Menu.View.Workspaces"; const int MODELNODE_PREVIEW_IMAGE_DIMENSIONS = 150; +const char EVENT_TIMELINE_ADDED[] = "Timeline Added"; +const char EVENT_TRANSITION_ADDED[] = "Transition Added"; +const char EVENT_STATE_ADDED[] = "State Added"; +const char EVENT_ANNOTATION_ADDED[] = "Annotation Added"; +const char EVENT_RESOURCE_IMPORTED[] = "Resource Imported "; +const char EVENT_ACTION_EXECUTED[] = "Action Executed "; + namespace Internal { enum { debug = 0 }; } diff --git a/src/plugins/qmldesigner/qmldesignerplugin.cpp b/src/plugins/qmldesigner/qmldesignerplugin.cpp index ff6110efb76..466d304955b 100644 --- a/src/plugins/qmldesigner/qmldesignerplugin.cpp +++ b/src/plugins/qmldesigner/qmldesignerplugin.cpp @@ -547,6 +547,17 @@ double QmlDesignerPlugin::formEditorDevicePixelRatio() return topLevelWindows.constFirst()->screen()->devicePixelRatio(); } +void QmlDesignerPlugin::emitUsageStatistics(const QString &identifier) +{ + QTC_ASSERT(instance(), return); + emit instance()->usageStatisticsNotifier(identifier); +} + +void QmlDesignerPlugin::emitUsageStatisticsContextAction(const QString &identifier) +{ + emitUsageStatistics(Constants::EVENT_ACTION_EXECUTED + identifier); +} + QmlDesignerPlugin *QmlDesignerPlugin::instance() { return m_instance; diff --git a/src/plugins/qmldesigner/qmldesignerplugin.h b/src/plugins/qmldesigner/qmldesignerplugin.h index 20dffbd5ba5..f5a8242ae74 100644 --- a/src/plugins/qmldesigner/qmldesignerplugin.h +++ b/src/plugins/qmldesigner/qmldesignerplugin.h @@ -82,6 +82,13 @@ public: static double formEditorDevicePixelRatio(); + static void emitUsageStatistics(const QString &identifier); + static void emitUsageStatisticsContextAction(const QString &identifier); + +signals: + void usageStatisticsNotifier(const QString &identifier); + + private: // functions void integrateIntoQtCreator(QWidget *modeWidget); void showDesigner(); diff --git a/src/plugins/qmljseditor/qmljsfindreferences.cpp b/src/plugins/qmljseditor/qmljsfindreferences.cpp index e5152be4f5a..000e1915879 100644 --- a/src/plugins/qmljseditor/qmljsfindreferences.cpp +++ b/src/plugins/qmljseditor/qmljsfindreferences.cpp @@ -25,14 +25,15 @@ #include "qmljsfindreferences.h" -#include +#include #include -#include -#include +#include #include #include -#include -#include +#include +#include +#include +#include #include #include @@ -47,15 +48,14 @@ #include "qmljseditorconstants.h" -#include -#include -#include -#include +#include #include #include -#include +#include #include -#include +#include +#include +#include #include diff --git a/src/plugins/qmljseditor/qmljsfindreferences.h b/src/plugins/qmljseditor/qmljsfindreferences.h index 41c8fc07d2c..aec4cb6c6d0 100644 --- a/src/plugins/qmljseditor/qmljsfindreferences.h +++ b/src/plugins/qmljseditor/qmljsfindreferences.h @@ -29,7 +29,6 @@ #include #include -#include #include #include diff --git a/src/plugins/qmlprofiler/qmlprofilertracefile.h b/src/plugins/qmlprofiler/qmlprofilertracefile.h index 60198ee3d45..b92198be912 100644 --- a/src/plugins/qmlprofiler/qmlprofilertracefile.h +++ b/src/plugins/qmlprofiler/qmlprofilertracefile.h @@ -34,7 +34,6 @@ #include -#include #include #include #include diff --git a/src/plugins/qtsupport/baseqtversion.cpp b/src/plugins/qtsupport/baseqtversion.cpp index f9eb26a4f06..331e30f9dd9 100644 --- a/src/plugins/qtsupport/baseqtversion.cpp +++ b/src/plugins/qtsupport/baseqtversion.cpp @@ -60,13 +60,12 @@ #include -#include -#include -#include -#include #include +#include +#include #include #include +#include #include @@ -1054,7 +1053,8 @@ QString BaseQtVersionPrivate::findHostBinary(HostBinaries binary) const if (HostOsInfo::isWindowsHost()) { possibleCommands << "uic.exe"; } else { - possibleCommands << "uic-qt4" << "uic4" << "uic"; + const QString majorString = QString::number(q->qtVersion().majorVersion); + possibleCommands << ("uic-qt" + majorString) << ("uic" + majorString) << "uic"; } break; case QScxmlc: diff --git a/src/plugins/valgrind/callgrind/callgrindparser.cpp b/src/plugins/valgrind/callgrind/callgrindparser.cpp index f481ff2dd94..dda06a50cde 100644 --- a/src/plugins/valgrind/callgrind/callgrindparser.cpp +++ b/src/plugins/valgrind/callgrind/callgrindparser.cpp @@ -464,7 +464,7 @@ void Parser::Private::parseCostItem(const char *begin, const char *end) if (currentCallData.calledFile == -1) { currentCallData.calledFile = currentDifferingFile != -1 ? currentDifferingFile : lastFile; //HACK: workaround issue where sometimes fi=??? lines are prepended to function calls - if (unknownFiles.contains(currentCallData.calledFile)) + if (unknownFiles.contains(quint64(currentCallData.calledFile))) currentCallData.calledFile = lastFile; } if (currentCallData.calledObject == -1) diff --git a/src/plugins/valgrind/valgrindengine.h b/src/plugins/valgrind/valgrindengine.h index 30ffbdb22fe..4eb3a119a4c 100644 --- a/src/plugins/valgrind/valgrindengine.h +++ b/src/plugins/valgrind/valgrindengine.h @@ -33,7 +33,6 @@ #include #include -#include namespace Valgrind { namespace Internal { diff --git a/src/tools/clangbackend/clangbackendmain.cpp b/src/tools/clangbackend/clangbackendmain.cpp index 571c4ebe3bc..56a4c9f8149 100644 --- a/src/tools/clangbackend/clangbackendmain.cpp +++ b/src/tools/clangbackend/clangbackendmain.cpp @@ -57,7 +57,7 @@ QString processArguments(QCoreApplication &application) } #ifdef Q_OS_WIN -extern "C" void __stdcall OutputDebugStringW(const wchar_t* msg); +#include static void messageOutput(QtMsgType type, const QMessageLogContext &/*context*/, const QString &msg) { diff --git a/src/tools/clangbackend/source/diagnosticsetiterator.h b/src/tools/clangbackend/source/diagnosticsetiterator.h index 72a98319550..0369e91999d 100644 --- a/src/tools/clangbackend/source/diagnosticsetiterator.h +++ b/src/tools/clangbackend/source/diagnosticsetiterator.h @@ -37,9 +37,15 @@ using uint = unsigned int; class DiagnosticSet; -class DiagnosticSetIterator : public std::iterator +class DiagnosticSetIterator { public: + using iterator_category = std::random_access_iterator_tag; + using value_type = Diagnostic; + using difference_type = uint; + using pointer = Diagnostic *; + using reference = Diagnostic &; + DiagnosticSetIterator(CXTranslationUnit translationUnit, CXDiagnosticSet cxDiagnosticSet, uint index) diff --git a/src/tools/clangbackend/source/tokenprocessoriterator.h b/src/tools/clangbackend/source/tokenprocessoriterator.h index 38edac85327..08bdbc1546f 100644 --- a/src/tools/clangbackend/source/tokenprocessoriterator.h +++ b/src/tools/clangbackend/source/tokenprocessoriterator.h @@ -38,9 +38,15 @@ class DiagnosticSet; class Diagnostic; template -class TokenProcessorIterator : public std::iterator +class TokenProcessorIterator { public: + using iterator_category = std::forward_iterator_tag; + using value_type = TokenInfo; + using difference_type = int; + using pointer = TokenInfo *; + using reference = TokenInfo &; + TokenProcessorIterator(std::vector::const_iterator cursorIterator, std::vector::const_iterator tokenIterator, std::vector ¤tOutputArgumentRanges) diff --git a/tests/unit/unittest/cppprojectinfogenerator-test.cpp b/tests/unit/unittest/cppprojectinfogenerator-test.cpp index ceb3c8b8aae..98eb8feeaa3 100644 --- a/tests/unit/unittest/cppprojectinfogenerator-test.cpp +++ b/tests/unit/unittest/cppprojectinfogenerator-test.cpp @@ -163,7 +163,7 @@ void ProjectInfoGenerator::SetUp() ProjectInfo ProjectInfoGenerator::generate() { - QFutureInterface fi; + QFutureInterface fi; ProjectExplorer::ConcreteToolChain aToolChain; projectUpdateInfo.rawProjectParts += rawProjectPart; diff --git a/tests/unit/unittest/gtest-creator-printing.cpp b/tests/unit/unittest/gtest-creator-printing.cpp index 706974f9833..b3e11310dee 100644 --- a/tests/unit/unittest/gtest-creator-printing.cpp +++ b/tests/unit/unittest/gtest-creator-printing.cpp @@ -415,6 +415,22 @@ std::ostream &operator<<(std::ostream &out, sqlite3_changeset_iter *iter) return out; } + +const char *toText(Operation operation) +{ + switch (operation) { + case Operation::Invalid: + return "Invalid"; + case Operation::Insert: + return "Invalid"; + case Operation::Update: + return "Invalid"; + case Operation::Delete: + return "Invalid"; + } + + return ""; +} } // namespace std::ostream &operator<<(std::ostream &out, const SessionChangeSet &changeset) @@ -437,25 +453,14 @@ std::ostream &operator<<(std::ostream &out, const SessionChangeSet &changeset) return out; } +std::ostream &operator<<(std::ostream &out, Operation operation) +{ + return out << toText(operation); +} + namespace SessionChangeSetInternal { namespace { -const char *toText(Operation operation) -{ - switch (operation) { - case Operation::Invalid: - return "Invalid"; - case Operation::Insert: - return "Invalid"; - case Operation::Update: - return "Invalid"; - case Operation::Delete: - return "Invalid"; - } - - return ""; -} - const char *toText(State state) { switch (state) { @@ -476,11 +481,6 @@ std::ostream &operator<<(std::ostream &out, SentinelIterator) return out << "sentinel"; } -std::ostream &operator<<(std::ostream &out, Operation operation) -{ - return out << toText(operation); -} - std::ostream &operator<<(std::ostream &out, State state) { return out << toText(state); diff --git a/tests/unit/unittest/gtest-creator-printing.h b/tests/unit/unittest/gtest-creator-printing.h index 5967ab3ead4..b3677637661 100644 --- a/tests/unit/unittest/gtest-creator-printing.h +++ b/tests/unit/unittest/gtest-creator-printing.h @@ -68,24 +68,25 @@ namespace Sqlite { class Value; class ValueView; class SessionChangeSet; +enum class Operation : char; std::ostream &operator<<(std::ostream &out, const Value &value); std::ostream &operator<<(std::ostream &out, const ValueView &value); +std::ostream &operator<<(std::ostream &out, Operation operation); std::ostream &operator<<(std::ostream &out, const SessionChangeSet &changeset); + namespace SessionChangeSetInternal { class ConstIterator; class ConstTupleIterator; class SentinelIterator; class Tuple; class ValueViews; -enum class Operation : char; enum class State : char; std::ostream &operator<<(std::ostream &out, SentinelIterator iterator); std::ostream &operator<<(std::ostream &out, const ConstIterator &iterator); std::ostream &operator<<(std::ostream &out, const ConstTupleIterator &iterator); std::ostream &operator<<(std::ostream &out, const Tuple &tuple); -std::ostream &operator<<(std::ostream &out, Operation operation); std::ostream &operator<<(std::ostream &out, State operation); std::ostream &operator<<(std::ostream &out, const ValueViews &valueViews); diff --git a/tests/unit/unittest/imagecache-test.cpp b/tests/unit/unittest/imagecache-test.cpp index f3f2c825180..dc64780f2bb 100644 --- a/tests/unit/unittest/imagecache-test.cpp +++ b/tests/unit/unittest/imagecache-test.cpp @@ -112,8 +112,8 @@ TEST_F(ImageCache, RequestImageRequestImageFromGenerator) .WillByDefault(Return(Sqlite::TimeStamp{123})); EXPECT_CALL(mockGenerator, - generateImage(Eq("/path/to/Component.qml"), Eq(Sqlite::TimeStamp{123}), _, _)) - .WillRepeatedly([&](auto &&, auto, auto &&callback, auto) { notification.notify(); }); + generateImage(Eq("/path/to/Component.qml"), _, Eq(Sqlite::TimeStamp{123}), _, _)) + .WillRepeatedly([&](auto, auto, auto, auto &&callback, auto) { notification.notify(); }); cache.requestImage("/path/to/Component.qml", mockCaptureCallback.AsStdFunction(), @@ -123,8 +123,8 @@ TEST_F(ImageCache, RequestImageRequestImageFromGenerator) TEST_F(ImageCache, RequestImageCallsCaptureCallbackWithImageFromGenerator) { - ON_CALL(mockGenerator, generateImage(Eq("/path/to/Component.qml"), _, _, _)) - .WillByDefault([&](auto &&, auto, auto &&callback, auto) { + ON_CALL(mockGenerator, generateImage(Eq("/path/to/Component.qml"), _, _, _, _)) + .WillByDefault([&](auto, auto, auto, auto &&callback, auto) { callback(QImage{image1}); notification.notify(); }); @@ -139,8 +139,8 @@ TEST_F(ImageCache, RequestImageCallsCaptureCallbackWithImageFromGenerator) TEST_F(ImageCache, RequestImageCallsAbortCallbackFromGenerator) { - ON_CALL(mockGenerator, generateImage(Eq("/path/to/Component.qml"), _, _, _)) - .WillByDefault([&](auto &&, auto, auto &&, auto &&abortCallback) { + ON_CALL(mockGenerator, generateImage(Eq("/path/to/Component.qml"), _, _, _, _)) + .WillByDefault([&](auto, auto, auto, auto &&, auto &&abortCallback) { abortCallback(); notification.notify(); }); @@ -217,8 +217,8 @@ TEST_F(ImageCache, RequestIconRequestImageFromGenerator) .WillByDefault(Return(Sqlite::TimeStamp{123})); EXPECT_CALL(mockGenerator, - generateImage(Eq("/path/to/Component.qml"), Eq(Sqlite::TimeStamp{123}), _, _)) - .WillRepeatedly([&](auto &&, auto, auto &&callback, auto) { notification.notify(); }); + generateImage(Eq("/path/to/Component.qml"), _, Eq(Sqlite::TimeStamp{123}), _, _)) + .WillRepeatedly([&](auto, auto, auto, auto &&callback, auto) { notification.notify(); }); cache.requestIcon("/path/to/Component.qml", mockCaptureCallback.AsStdFunction(), @@ -228,8 +228,8 @@ TEST_F(ImageCache, RequestIconRequestImageFromGenerator) TEST_F(ImageCache, RequestIconCallsCaptureCallbackWithImageFromGenerator) { - ON_CALL(mockGenerator, generateImage(Eq("/path/to/Component.qml"), _, _, _)) - .WillByDefault([&](auto &&, auto, auto &&callback, auto) { + ON_CALL(mockGenerator, generateImage(Eq("/path/to/Component.qml"), _, _, _, _)) + .WillByDefault([&](auto, auto, auto, auto &&callback, auto) { callback(QImage{image1}); notification.notify(); }); @@ -244,8 +244,8 @@ TEST_F(ImageCache, RequestIconCallsCaptureCallbackWithImageFromGenerator) TEST_F(ImageCache, RequestIconCallsAbortCallbackFromGenerator) { - ON_CALL(mockGenerator, generateImage(Eq("/path/to/Component.qml"), _, _, _)) - .WillByDefault([&](auto &&, auto, auto &&, auto &&abortCallback) { + ON_CALL(mockGenerator, generateImage(Eq("/path/to/Component.qml"), _, _, _, _)) + .WillByDefault([&](auto, auto, auto, auto &&, auto &&abortCallback) { abortCallback(); notification.notify(); }); @@ -260,8 +260,8 @@ TEST_F(ImageCache, RequestIconCallsAbortCallbackFromGenerator) TEST_F(ImageCache, CleanRemovesEntries) { - EXPECT_CALL(mockGenerator, generateImage(_, _, _, _)) - .WillRepeatedly([&](auto &&, auto, auto &&mockCaptureCallback, auto &&) { + EXPECT_CALL(mockGenerator, generateImage(_, _, _, _, _)) + .WillRepeatedly([&](auto, auto, auto, auto &&mockCaptureCallback, auto &&) { mockCaptureCallback(QImage{}); waitInThread.wait(); }); @@ -280,9 +280,9 @@ TEST_F(ImageCache, CleanRemovesEntries) TEST_F(ImageCache, CleanCallsAbort) { - ON_CALL(mockGenerator, generateImage(_, _, _, _)) + ON_CALL(mockGenerator, generateImage(_, _, _, _, _)) .WillByDefault( - [&](auto &&, auto, auto &&mockCaptureCallback, auto &&) { waitInThread.wait(); }); + [&](auto, auto, auto, auto &&mockCaptureCallback, auto &&) { waitInThread.wait(); }); cache.requestIcon("/path/to/Component1.qml", mockCaptureCallback.AsStdFunction(), mockAbortCallback.AsStdFunction()); @@ -310,8 +310,8 @@ TEST_F(ImageCache, AfterCleanNewJobsWorks) { cache.clean(); - EXPECT_CALL(mockGenerator, generateImage(Eq("/path/to/Component.qml"), _, _, _)) - .WillRepeatedly([&](auto &&, auto, auto &&, auto &&) { notification.notify(); }); + EXPECT_CALL(mockGenerator, generateImage(Eq("/path/to/Component.qml"), _, _, _, _)) + .WillRepeatedly([&](auto, auto, auto, auto &&, auto &&) { notification.notify(); }); cache.requestIcon("/path/to/Component.qml", mockCaptureCallback.AsStdFunction(), @@ -319,4 +319,73 @@ TEST_F(ImageCache, AfterCleanNewJobsWorks) notification.wait(); } +TEST_F(ImageCache, WaitForFinished) +{ + ON_CALL(mockStorage, fetchImage(_, _)) + .WillByDefault(Return(QmlDesigner::ImageCacheStorageInterface::Entry{image1, true})); + cache.requestImage("/path/to/Component1.qml", + mockCaptureCallback.AsStdFunction(), + mockAbortCallback.AsStdFunction()); + cache.requestImage("/path/to/Component2.qml", + mockCaptureCallback.AsStdFunction(), + mockAbortCallback.AsStdFunction()); + + EXPECT_CALL(mockCaptureCallback, Call(_)).Times(2); + + cache.waitForFinished(); +} + +TEST_F(ImageCache, WaitForFinishedInGenerator) +{ + EXPECT_CALL(mockGenerator, waitForFinished()); + + cache.waitForFinished(); +} + +TEST_F(ImageCache, RequestImageWithStateFetchesImageFromStorage) +{ + EXPECT_CALL(mockStorage, fetchImage(Eq("/path/to/Component.qml+state1"), _)) + .WillRepeatedly([&](Utils::SmallStringView, auto) { + notification.notify(); + return QmlDesigner::ImageCacheStorageInterface::Entry{{}, false}; + }); + + cache.requestImage("/path/to/Component.qml", + mockCaptureCallback.AsStdFunction(), + mockAbortCallback.AsStdFunction(), + "state1"); + notification.wait(); +} + +TEST_F(ImageCache, RequestIconWithStateFetchesImageFromStorage) +{ + EXPECT_CALL(mockStorage, fetchIcon(Eq("/path/to/Component.qml+state1"), _)) + .WillRepeatedly([&](Utils::SmallStringView, auto) { + notification.notify(); + return QmlDesigner::ImageCacheStorageInterface::Entry{{}, false}; + }); + + cache.requestIcon("/path/to/Component.qml", + mockCaptureCallback.AsStdFunction(), + mockAbortCallback.AsStdFunction(), + "state1"); + notification.wait(); +} + +TEST_F(ImageCache, RequestImageWithStateRequestImageFromGenerator) +{ + ON_CALL(mockTimeStampProvider, timeStamp(Eq("/path/to/Component.qml"))) + .WillByDefault(Return(Sqlite::TimeStamp{123})); + + EXPECT_CALL(mockGenerator, + generateImage(Eq("/path/to/Component.qml"), Eq("state1"), Eq(Sqlite::TimeStamp{123}), _, _)) + .WillRepeatedly([&](auto, auto, auto, auto &&callback, auto) { notification.notify(); }); + + cache.requestImage("/path/to/Component.qml", + mockCaptureCallback.AsStdFunction(), + mockAbortCallback.AsStdFunction(), + "state1"); + notification.wait(); +} + } // namespace diff --git a/tests/unit/unittest/imagecachecollectormock.h b/tests/unit/unittest/imagecachecollectormock.h index 93520c418d3..39b06bb5252 100644 --- a/tests/unit/unittest/imagecachecollectormock.h +++ b/tests/unit/unittest/imagecachecollectormock.h @@ -35,6 +35,7 @@ public: MOCK_METHOD(void, start, (Utils::SmallStringView filePath, + Utils::SmallStringView state, ImageCacheCollectorInterface::CaptureCallback captureCallback, ImageCacheCollectorInterface::AbortCallback abortCallback), (override)); diff --git a/tests/unit/unittest/imagecachegenerator-test.cpp b/tests/unit/unittest/imagecachegenerator-test.cpp index 3b183d00672..5ed377bbce9 100644 --- a/tests/unit/unittest/imagecachegenerator-test.cpp +++ b/tests/unit/unittest/imagecachegenerator-test.cpp @@ -63,24 +63,25 @@ protected: TEST_F(ImageCacheGenerator, CallsCollectorWithCaptureCallback) { - EXPECT_CALL(collectorMock, start(Eq("name"), _, _)) - .WillRepeatedly([&](auto, auto captureCallback, auto) { captureCallback(QImage{image1}); }); + EXPECT_CALL(collectorMock, start(Eq("name"), _, _, _)) + .WillRepeatedly( + [&](auto, auto, auto captureCallback, auto) { captureCallback(QImage{image1}); }); EXPECT_CALL(imageCallbackMock, Call(_)).WillRepeatedly([&](const QImage &) { notification.notify(); }); - generator.generateImage("name", {}, imageCallbackMock.AsStdFunction(), {}); + generator.generateImage("name", {}, {}, imageCallbackMock.AsStdFunction(), {}); notification.wait(); } TEST_F(ImageCacheGenerator, CallsCollectorOnlyIfNotProcessing) { - EXPECT_CALL(collectorMock, start(Eq("name"), _, _)).WillRepeatedly([&](auto, auto, auto) { + EXPECT_CALL(collectorMock, start(Eq("name"), _, _, _)).WillRepeatedly([&](auto, auto, auto, auto) { notification.notify(); }); - generator.generateImage("name", {}, imageCallbackMock.AsStdFunction(), {}); - generator.generateImage("name", {}, imageCallbackMock.AsStdFunction(), {}); + generator.generateImage("name", {}, {}, imageCallbackMock.AsStdFunction(), {}); + generator.generateImage("name", {}, {}, imageCallbackMock.AsStdFunction(), {}); notification.wait(2); } @@ -88,37 +89,39 @@ TEST_F(ImageCacheGenerator, ProcessTaskAfterFirstFinished) { ON_CALL(imageCallbackMock, Call(_)).WillByDefault([&](const QImage &) { notification.notify(); }); - EXPECT_CALL(collectorMock, start(Eq("name"), _, _)).WillOnce([&](auto, auto captureCallback, auto) { - captureCallback(QImage{image1}); - }); - EXPECT_CALL(collectorMock, start(Eq("name2"), _, _)).WillOnce([&](auto, auto captureCallback, auto) { - captureCallback(QImage{image1}); - }); + EXPECT_CALL(collectorMock, start(Eq("name"), _, _, _)) + .WillOnce([&](auto, auto, auto captureCallback, auto) { captureCallback(QImage{image1}); }); + EXPECT_CALL(collectorMock, start(Eq("name2"), _, _, _)) + .WillOnce([&](auto, auto, auto captureCallback, auto) { captureCallback(QImage{image1}); }); - generator.generateImage("name", {}, imageCallbackMock.AsStdFunction(), {}); - generator.generateImage("name2", {}, imageCallbackMock.AsStdFunction(), {}); + generator.generateImage("name", {}, {}, imageCallbackMock.AsStdFunction(), {}); + generator.generateImage("name2", {}, {}, imageCallbackMock.AsStdFunction(), {}); notification.wait(2); } TEST_F(ImageCacheGenerator, DontCrashAtDestructingGenerator) { - ON_CALL(collectorMock, start(Eq("name"), _, _)).WillByDefault([&](auto, auto captureCallback, auto) { - captureCallback(QImage{image1}); - }); + ON_CALL(collectorMock, start(Eq("name"), _, _, _)) + .WillByDefault( + [&](auto, auto, auto captureCallback, auto) { captureCallback(QImage{image1}); }); generator.generateImage("name", + {}, {}, imageCallbackMock.AsStdFunction(), abortCallbackMock.AsStdFunction()); generator.generateImage("name2", + {}, {}, imageCallbackMock.AsStdFunction(), abortCallbackMock.AsStdFunction()); generator.generateImage("name3", + {}, {}, imageCallbackMock.AsStdFunction(), abortCallbackMock.AsStdFunction()); generator.generateImage("name4", + {}, {}, imageCallbackMock.AsStdFunction(), abortCallbackMock.AsStdFunction()); @@ -126,27 +129,27 @@ TEST_F(ImageCacheGenerator, DontCrashAtDestructingGenerator) TEST_F(ImageCacheGenerator, StoreImage) { - ON_CALL(collectorMock, start(Eq("name"), _, _)).WillByDefault([&](auto, auto captureCallback, auto) { - captureCallback(QImage{image1}); - }); + ON_CALL(collectorMock, start(Eq("name"), _, _, _)) + .WillByDefault( + [&](auto, auto, auto captureCallback, auto) { captureCallback(QImage{image1}); }); EXPECT_CALL(storageMock, storeImage(Eq("name"), Eq(Sqlite::TimeStamp{11}), Eq(image1))) .WillRepeatedly([&](auto, auto, auto) { notification.notify(); }); - generator.generateImage("name", {11}, imageCallbackMock.AsStdFunction(), {}); + generator.generateImage("name", {}, {11}, imageCallbackMock.AsStdFunction(), {}); notification.wait(); } TEST_F(ImageCacheGenerator, StoreNullImage) { - ON_CALL(collectorMock, start(Eq("name"), _, _)).WillByDefault([&](auto, auto captureCallback, auto) { - captureCallback(QImage{}); - }); + ON_CALL(collectorMock, start(Eq("name"), _, _, _)) + .WillByDefault([&](auto, auto, auto captureCallback, auto) { captureCallback(QImage{}); }); EXPECT_CALL(storageMock, storeImage(Eq("name"), Eq(Sqlite::TimeStamp{11}), Eq(QImage{}))) .WillRepeatedly([&](auto, auto, auto) { notification.notify(); }); generator.generateImage("name", + {}, {11}, imageCallbackMock.AsStdFunction(), abortCallbackMock.AsStdFunction()); @@ -155,21 +158,22 @@ TEST_F(ImageCacheGenerator, StoreNullImage) TEST_F(ImageCacheGenerator, AbortCallback) { - ON_CALL(collectorMock, start(Eq("name"), _, _)).WillByDefault([&](auto, auto captureCallback, auto) { - captureCallback(QImage{image1}); - }); - ON_CALL(collectorMock, start(Eq("name2"), _, _)).WillByDefault([&](auto, auto, auto abortCallback) { - abortCallback(); - }); + ON_CALL(collectorMock, start(Eq("name"), _, _, _)) + .WillByDefault( + [&](auto, auto, auto captureCallback, auto) { captureCallback(QImage{image1}); }); + ON_CALL(collectorMock, start(Eq("name2"), _, _, _)) + .WillByDefault([&](auto, auto, auto, auto abortCallback) { abortCallback(); }); EXPECT_CALL(imageCallbackMock, Call(_)).WillOnce([&](const QImage &) { notification.notify(); }); EXPECT_CALL(abortCallbackMock, Call()).WillOnce([&]() { notification.notify(); }); generator.generateImage("name", + {}, {}, imageCallbackMock.AsStdFunction(), abortCallbackMock.AsStdFunction()); generator.generateImage("name2", + {}, {}, imageCallbackMock.AsStdFunction(), abortCallbackMock.AsStdFunction()); @@ -178,7 +182,7 @@ TEST_F(ImageCacheGenerator, AbortCallback) TEST_F(ImageCacheGenerator, StoreNullImageForAbortCallback) { - ON_CALL(collectorMock, start(_, _, _)).WillByDefault([&](auto, auto, auto abortCallback) { + ON_CALL(collectorMock, start(_, _, _, _)).WillByDefault([&](auto, auto, auto, auto abortCallback) { abortCallback(); }); @@ -186,6 +190,7 @@ TEST_F(ImageCacheGenerator, StoreNullImageForAbortCallback) .WillOnce([&](auto, auto, auto) { notification.notify(); }); generator.generateImage("name", + {}, {11}, imageCallbackMock.AsStdFunction(), abortCallbackMock.AsStdFunction()); @@ -194,13 +199,13 @@ TEST_F(ImageCacheGenerator, StoreNullImageForAbortCallback) TEST_F(ImageCacheGenerator, AbortForEmptyImage) { - ON_CALL(collectorMock, start(Eq("name"), _, _)).WillByDefault([&](auto, auto captureCallback, auto) { - captureCallback(QImage{}); - }); + ON_CALL(collectorMock, start(Eq("name"), _, _, _)) + .WillByDefault([&](auto, auto, auto captureCallback, auto) { captureCallback(QImage{}); }); EXPECT_CALL(abortCallbackMock, Call()).WillOnce([&]() { notification.notify(); }); generator.generateImage("name", + {}, {}, imageCallbackMock.AsStdFunction(), abortCallbackMock.AsStdFunction()); @@ -209,17 +214,18 @@ TEST_F(ImageCacheGenerator, AbortForEmptyImage) TEST_F(ImageCacheGenerator, CallWalCheckpointFullIfQueueIsEmpty) { - ON_CALL(collectorMock, start(Eq("name"), _, _)).WillByDefault([&](auto, auto captureCallback, auto) { - captureCallback({}); - }); + ON_CALL(collectorMock, start(Eq("name"), _, _, _)) + .WillByDefault([&](auto, auto, auto captureCallback, auto) { captureCallback({}); }); EXPECT_CALL(storageMock, walCheckpointFull()).WillRepeatedly([&]() { notification.notify(); }); generator.generateImage("name", + {}, {11}, imageCallbackMock.AsStdFunction(), abortCallbackMock.AsStdFunction()); generator.generateImage("name2", + {}, {11}, imageCallbackMock.AsStdFunction(), abortCallbackMock.AsStdFunction()); @@ -228,15 +234,17 @@ TEST_F(ImageCacheGenerator, CallWalCheckpointFullIfQueueIsEmpty) TEST_F(ImageCacheGenerator, CleanIsCallingAbortCallback) { - ON_CALL(collectorMock, start(_, _, _)).WillByDefault([&](auto, auto captureCallback, auto) { + ON_CALL(collectorMock, start(_, _, _, _)).WillByDefault([&](auto, auto, auto captureCallback, auto) { captureCallback({}); waitInThread.wait(); }); generator.generateImage("name", + {}, {11}, imageCallbackMock.AsStdFunction(), abortCallbackMock.AsStdFunction()); generator.generateImage("name2", + {}, {11}, imageCallbackMock.AsStdFunction(), abortCallbackMock.AsStdFunction()); @@ -247,4 +255,34 @@ TEST_F(ImageCacheGenerator, CleanIsCallingAbortCallback) waitInThread.notify(); } +TEST_F(ImageCacheGenerator, WaitForFinished) +{ + ON_CALL(collectorMock, start(_, _, _, _)).WillByDefault([&](auto, auto, auto captureCallback, auto) { + captureCallback(QImage{image1}); + }); + generator.generateImage("name", + {}, + {11}, + imageCallbackMock.AsStdFunction(), + abortCallbackMock.AsStdFunction()); + generator.generateImage("name2", + {}, + {11}, + imageCallbackMock.AsStdFunction(), + abortCallbackMock.AsStdFunction()); + + EXPECT_CALL(imageCallbackMock, Call(_)).Times(2); + + generator.waitForFinished(); +} + +TEST_F(ImageCacheGenerator, CallsCollectorWithState) +{ + EXPECT_CALL(collectorMock, start(Eq("name"), Eq("state1"), _, _)) + .WillRepeatedly([&](auto, auto, auto, auto) { notification.notify(); }); + + generator.generateImage("name", "state1", {}, imageCallbackMock.AsStdFunction(), {}); + notification.wait(); +} + } // namespace diff --git a/tests/unit/unittest/mockimagecachegenerator.h b/tests/unit/unittest/mockimagecachegenerator.h index ffe8d9c7097..ffe8819b41c 100644 --- a/tests/unit/unittest/mockimagecachegenerator.h +++ b/tests/unit/unittest/mockimagecachegenerator.h @@ -35,9 +35,11 @@ public: MOCK_METHOD(void, generateImage, (Utils::SmallStringView name, + Utils::SmallStringView state, Sqlite::TimeStamp timeStamp, CaptureCallback &&captureCallback, AbortCallback &&abortCallback), (override)); MOCK_METHOD(void, clean, (), (override)); + MOCK_METHOD(void, waitForFinished, (), (override)); }; diff --git a/tests/unit/unittest/sqlitesessions-test.cpp b/tests/unit/unittest/sqlitesessions-test.cpp index 35b6bf1fe89..31c71375511 100644 --- a/tests/unit/unittest/sqlitesessions-test.cpp +++ b/tests/unit/unittest/sqlitesessions-test.cpp @@ -36,9 +36,9 @@ namespace { +using Sqlite::Operation; using Sqlite::SessionChangeSet; using Sqlite::SessionChangeSets; -using Sqlite::SessionChangeSetInternal::Operation; using Sqlite::SessionChangeSetInternal::ValueViews; class DatabaseExecute diff --git a/tests/unit/unittest/unittests-main.cpp b/tests/unit/unittest/unittests-main.cpp index 6704a08034c..f3b81021be3 100644 --- a/tests/unit/unittest/unittests-main.cpp +++ b/tests/unit/unittest/unittests-main.cpp @@ -36,13 +36,23 @@ #include #endif +class Environment : public testing::Environment +{ +public: + void SetUp() override + { + const QString temporayDirectoryPath = QDir::tempPath() + "/QtCreator-UnitTests-XXXXXX"; + Utils::TemporaryDirectory::setMasterTemporaryDirectory(temporayDirectoryPath); + qputenv("TMPDIR", Utils::TemporaryDirectory::masterDirectoryPath().toUtf8()); + qputenv("TEMP", Utils::TemporaryDirectory::masterDirectoryPath().toUtf8()); + } + + void TearDown() override {} +}; + int main(int argc, char *argv[]) { Sqlite::Database::activateLogging(); - const QString temporayDirectoryPath = QDir::tempPath() +"/QtCreator-UnitTests-XXXXXX"; - Utils::TemporaryDirectory::setMasterTemporaryDirectory(temporayDirectoryPath); - qputenv("TMPDIR", Utils::TemporaryDirectory::masterDirectoryPath().toUtf8()); - qputenv("TEMP", Utils::TemporaryDirectory::masterDirectoryPath().toUtf8()); QCoreApplication application(argc, argv); @@ -51,6 +61,9 @@ int main(int argc, char *argv[]) benchmark::Initialize(&argc, argv); #endif + auto environment = std::make_unique(); + testing::AddGlobalTestEnvironment(environment.release()); + int testsHaveErrors = RUN_ALL_TESTS(); #ifdef WITH_BENCHMARKS